25 Commits
cx4 ... v0.1.1a

Author SHA1 Message Date
ikari
a7c1a29f10 add changelog 2011-12-24 23:06:28 +01:00
ikari
90b91583a1 Firmware: use FatFS FASTSEEK option for MSU1 file access 2011-12-19 22:32:27 +01:00
ikari
20c2cdb961 Firmware/bootloader: add 'fresh' Makefile target (erase+program) 2011-12-19 22:29:19 +01:00
ikari
dc01edfe9a FPGA: add test suite 2011-12-19 22:26:09 +01:00
ikari
014cf46a69 SNES: add test suite (SNES side) 2011-12-19 22:22:51 +01:00
ikari
0a6c7f125b Firmware: add test suite 2011-12-19 22:17:49 +01:00
ikari
72642321a2 SuperCIC/key: fix unreliable pair mode entry (sync with lock) 2011-12-18 18:41:00 +01:00
ikari
37a9f09a78 Menu: simplify some memory accesses 2011-12-16 19:19:51 +01:00
ikari
d65d657ff7 Firmware: increase ROM space for directory structure 2011-12-16 19:18:09 +01:00
ikari
39b78ae91c Firmware: SD debugging + minor cleanups 2011-12-16 19:16:31 +01:00
ikari
c97278c3d6 Firmware: adjust to reduced bootloader size 2011-12-16 19:08:38 +01:00
ikari
e880fac0ba Firmware: disable some debug messages 2011-12-16 19:07:41 +01:00
ikari
4a9d40b841 Firmware: update version number 2011-12-16 19:06:02 +01:00
ikari
a474ccf475 Firmware/CLI: Add 'rm' command 2011-12-16 19:03:01 +01:00
ikari
e5285f8196 Firmware/bootloader: reduce bootloader size to 8192 bytes 2011-12-10 20:33:52 +01:00
ikari
9943eca294 Firmware/bootloader: change CPU frequency from 92MHz to 96MHz 2011-12-10 20:32:48 +01:00
ikari
d1919c5f14 PCB/Rev.E: update schematic, PCB and component diagram with recent changes 2011-12-02 10:01:37 +01:00
ikari
aabed6e40c PCB/Rev.E: component layout diagrams 2011-12-02 09:24:46 +01:00
ikari
d94b435511 PCB Rev.E: add BOM 2011-11-11 00:23:15 +01:00
ikari
93a12f3ca1 FPGA: fix occasional erroneous write inhibit 2011-11-10 23:41:33 +01:00
ikari
bd1f5215db firmware: fix db entry linking on bank switch 2011-11-10 18:10:26 +01:00
ikari
08cace5c12 firmware: increase qsort entry limit to 2048 2011-11-10 18:06:22 +01:00
ikari
68f255d75b firmware, FPGA: fix for some SD cards 2011-11-10 17:54:52 +01:00
ikari
3fda86125c firmware: speed up directory scanning 2011-11-10 15:31:58 +01:00
ikari
60efa60bb4 Merge branch 'cx4' into develop 2011-11-01 22:04:59 +01:00
133 changed files with 19976 additions and 2415 deletions

13
CHANGELOG Normal file
View File

@@ -0,0 +1,13 @@
v0.1.1
======
* initial public release
v0.1.1a (bugfix release)
========================
* Fixes:
- SuperCIC pair mode was erroneously enabled in firmware binary
- SNES menu crashed on empty database

View File

@@ -64,6 +64,7 @@ processor p12f629
; 0x4d buffer for eeprom access
; 0x4e loop variable for longwait
; 0x4f loop variable for wait
; 0x5c GPIO buffer variable for pair mode allow
; 0x5d 0: SuperCIC pair mode available flag
; 0x5e SuperCIC pair mode detect (phase 1)
; 0x5f SuperCIC pair mode detect (phase 2)
@@ -90,8 +91,8 @@ isr
clrf 0x5f ; clear pair mode detect
bsf 0x5f, 1 ;
clrf 0x5d ; clear pair mode available
nop
nop
clrf 0x5c ; clear pair mode allow buffer
bsf 0x5c, 3 ; assume disallow
bsf INTCON, 7 ; re-enable interrupts (ISR will continue as main)
goto main
init
@@ -296,8 +297,8 @@ swapskip
; indirect access, no post increment, etc.
mangle
call mangle_lock
nop
nop
movf GPIO, w ; buffer GPIO state
movwf 0x5c ; for pair mode "transaction"
mangle_key
movf 0x2f, w
movwf 0x20
@@ -459,7 +460,7 @@ mangle_key_withskip
;-------pair mode code-------
bcf GPIO, 0
movf GPIO, w
btfss GPIO, 3
btfss 0x5c, 3
bsf GPIO, 0
movwf 0x5e
movf GPIO, w
@@ -642,7 +643,7 @@ mangle_lock_withskip
goto scic_pair_skip1
btfsc 0x5f, 1
goto scic_pair_skip2
btfsc GPIO, 3
btfsc 0x5c, 3
goto scic_pair_skip3
goto supercic_pairmode
scic_pair_skip1

View File

@@ -1,4 +1,4 @@
EESchema Schematic File Version 2 date Fri 29 Jul 2011 09:56:34 PM CEST
EESchema Schematic File Version 2 date Fri 02 Dec 2011 09:50:04 AM CET
LIBS:power
LIBS:device
LIBS:transistors
@@ -47,7 +47,7 @@ $Descr A3 16535 11700
encoding utf-8
Sheet 6 6
Title "sd2snes Mark II"
Date "24 jul 2011"
Date "2 dec 2011"
Rev "C"
Comp "Maximilian Rehkopf"
Comment1 ""

View File

@@ -1,4 +1,4 @@
EESchema Schematic File Version 2 date Fri 29 Jul 2011 09:56:34 PM CEST
EESchema Schematic File Version 2 date Fri 02 Dec 2011 09:50:04 AM CET
LIBS:power
LIBS:device
LIBS:transistors
@@ -47,7 +47,7 @@ $Descr A4 11700 8267
encoding utf-8
Sheet 4 6
Title "sd2snes Mark II"
Date "24 jul 2011"
Date "2 dec 2011"
Rev "C"
Comp "Maximilian Rehkopf"
Comment1 ""
@@ -1034,7 +1034,7 @@ L C C409
U 1 1 4BEECBD1
P 3100 6600
F 0 "C409" H 3150 6700 50 0000 L CNN
F 1 "22p" H 3150 6500 50 0000 L CNN
F 1 "10p" H 3150 6500 50 0000 L CNN
F 2 "SM0805_FIXEDMASK" H 3100 6600 60 0001 C CNN
1 3100 6600
1 0 0 -1
@@ -1044,7 +1044,7 @@ L C C408
U 1 1 4BEECBCD
P 2500 6600
F 0 "C408" H 2550 6700 50 0000 L CNN
F 1 "22p" H 2550 6500 50 0000 L CNN
F 1 "10p" H 2550 6500 50 0000 L CNN
F 2 "SM0805_FIXEDMASK" H 2500 6600 60 0001 C CNN
1 2500 6600
1 0 0 -1

View File

@@ -1,4 +1,4 @@
EESchema Schematic File Version 2 date Fri 29 Jul 2011 09:56:34 PM CEST
EESchema Schematic File Version 2 date Fri 02 Dec 2011 09:50:04 AM CET
LIBS:power
LIBS:device
LIBS:transistors
@@ -47,7 +47,7 @@ $Descr A4 11700 8267
encoding utf-8
Sheet 3 6
Title "sd2snes Mark II"
Date "24 jul 2011"
Date "2 dec 2011"
Rev "C"
Comp "Maximilian Rehkopf"
Comment1 ""

View File

@@ -1,4 +1,4 @@
EESchema Schematic File Version 2 date Fri 29 Jul 2011 09:56:34 PM CEST
EESchema Schematic File Version 2 date Fri 02 Dec 2011 09:50:04 AM CET
LIBS:power
LIBS:device
LIBS:transistors
@@ -47,7 +47,7 @@ $Descr A4 11700 8267
encoding utf-8
Sheet 5 6
Title "sd2snes Mark II"
Date "24 jul 2011"
Date "2 dec 2011"
Rev "C"
Comp "Maximilian Rehkopf"
Comment1 ""
@@ -55,6 +55,8 @@ Comment2 ""
Comment3 ""
Comment4 ""
$EndDescr
Text Notes 4900 5900 0 50 ~ 0
Stuff with 0603 ferrite bead
Wire Wire Line
5750 5500 5900 5500
Wire Wire Line
@@ -334,7 +336,7 @@ L JUMPER JP341
U 1 1 4DB35D41
P 5450 5500
F 0 "JP341" H 5450 5650 60 0000 C CNN
F 1 "JUMPER" H 5450 5420 40 0000 C CNN
F 1 "FB 0603" H 5450 5420 40 0000 C CNN
1 5450 5500
1 0 0 -1
$EndComp

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
EESchema Schematic File Version 2 date Fri 29 Jul 2011 09:56:34 PM CEST
EESchema Schematic File Version 2 date Fri 02 Dec 2011 09:50:04 AM CET
LIBS:power
LIBS:device
LIBS:transistors
@@ -47,7 +47,7 @@ $Descr A4 11700 8267
encoding utf-8
Sheet 1 6
Title "sd2snes Mark II"
Date "24 jul 2011"
Date "2 dec 2011"
Rev "E"
Comp "Maximilian Rehkopf"
Comment1 ""

View File

@@ -1,4 +1,4 @@
EESchema Schematic File Version 2 date Fri 29 Jul 2011 09:56:34 PM CEST
EESchema Schematic File Version 2 date Fri 02 Dec 2011 09:50:04 AM CET
LIBS:power
LIBS:device
LIBS:transistors
@@ -47,7 +47,7 @@ $Descr A3 16535 11700
encoding utf-8
Sheet 2 6
Title "sd2snes Mark II"
Date "24 jul 2011"
Date "2 dec 2011"
Rev "C"
Comp "Maximilian Rehkopf"
Comment1 ""
@@ -855,7 +855,7 @@ L R_PACK4 RA114
U 1 1 4D97B45F
P 15250 4750
F 0 "RA114" H 15250 4600 40 0000 C CNN
F 1 "220" H 15250 4950 40 0000 C CNN
F 1 "100" H 15250 4950 40 0000 C CNN
1 15250 4750
1 0 0 -1
$EndComp
@@ -864,7 +864,7 @@ L R_PACK4 RA113
U 1 1 4D97B45C
P 15250 4350
F 0 "RA113" H 15250 4800 40 0000 C CNN
F 1 "220" H 15250 4550 40 0000 C CNN
F 1 "100" H 15250 4550 40 0000 C CNN
1 15250 4350
1 0 0 -1
$EndComp
@@ -913,7 +913,7 @@ L R_PACK4 RA108
U 1 1 4D963119
P 4150 8350
F 0 "RA108" H 4150 8300 40 0000 C CNN
F 1 "220" H 4150 8550 40 0000 C CNN
F 1 "100" H 4150 8550 40 0000 C CNN
1 4150 8350
-1 0 0 -1
$EndComp
@@ -922,7 +922,7 @@ L R_PACK4 RA107
U 1 1 4D963117
P 4150 7950
F 0 "RA107" H 4150 8400 40 0000 C CNN
F 1 "220" H 4150 8150 40 0000 C CNN
F 1 "100" H 4150 8150 40 0000 C CNN
1 4150 7950
-1 0 0 -1
$EndComp
@@ -931,7 +931,7 @@ L R_PACK4 RA106
U 1 1 4D963115
P 4150 7350
F 0 "RA106" H 4150 7300 40 0000 C CNN
F 1 "220" H 4150 7550 40 0000 C CNN
F 1 "100" H 4150 7550 40 0000 C CNN
1 4150 7350
-1 0 0 -1
$EndComp
@@ -940,7 +940,7 @@ L R_PACK4 RA105
U 1 1 4D96310E
P 4150 6950
F 0 "RA105" H 4150 7400 40 0000 C CNN
F 1 "220" H 4150 7150 40 0000 C CNN
F 1 "100" H 4150 7150 40 0000 C CNN
1 4150 6950
-1 0 0 -1
$EndComp
@@ -949,7 +949,7 @@ L R_PACK4 RA112
U 1 1 4D96310C
P 4150 4650
F 0 "RA112" H 4150 4600 40 0000 C CNN
F 1 "220" H 4150 4850 40 0000 C CNN
F 1 "100" H 4150 4850 40 0000 C CNN
1 4150 4650
1 0 0 -1
$EndComp
@@ -958,7 +958,7 @@ L R_PACK4 RA111
U 1 1 4D96310A
P 4150 4250
F 0 "RA111" H 4150 4700 40 0000 C CNN
F 1 "220" H 4150 4450 40 0000 C CNN
F 1 "100" H 4150 4450 40 0000 C CNN
1 4150 4250
-1 0 0 -1
$EndComp
@@ -967,7 +967,7 @@ L R_PACK4 RA110
U 1 1 4D963107
P 4150 3650
F 0 "RA110" H 4150 3600 40 0000 C CNN
F 1 "220" H 4150 3850 40 0000 C CNN
F 1 "100" H 4150 3850 40 0000 C CNN
1 4150 3650
-1 0 0 -1
$EndComp
@@ -976,7 +976,7 @@ L R_PACK4 RA109
U 1 1 4D963103
P 4150 3250
F 0 "RA109" H 4150 3700 40 0000 C CNN
F 1 "220" H 4150 3450 40 0000 C CNN
F 1 "100" H 4150 3450 40 0000 C CNN
1 4150 3250
-1 0 0 -1
$EndComp
@@ -985,7 +985,7 @@ L R_PACK4 RA102
U 1 1 4D9630F4
P 12400 3750
F 0 "RA102" H 12400 3700 40 0000 C CNN
F 1 "220" H 12400 3950 40 0000 C CNN
F 1 "100" H 12400 3950 40 0000 C CNN
1 12400 3750
1 0 0 -1
$EndComp
@@ -994,7 +994,7 @@ L R_PACK4 RA101
U 1 1 4D9630F0
P 12400 3350
F 0 "RA101" H 12400 3800 40 0000 C CNN
F 1 "220" H 12400 3550 40 0000 C CNN
F 1 "100" H 12400 3550 40 0000 C CNN
1 12400 3350
1 0 0 -1
$EndComp
@@ -1005,7 +1005,7 @@ P 12400 4750
AR Path="/4B6E16F2/4D95CDCD" Ref="RP?" Part="1"
AR Path="/4B6E16F2/4D95CDD4" Ref="RA104" Part="1"
F 0 "RA104" H 12400 4650 40 0000 C CNN
F 1 "220" H 12400 4950 40 0000 C CNN
F 1 "FB" H 12400 4950 40 0000 C CNN
1 12400 4750
1 0 0 -1
$EndComp
@@ -1014,7 +1014,7 @@ L R_PACK4 RA103
U 1 1 4D95CDCD
P 12400 4350
F 0 "RA103" H 12400 4800 40 0000 C CNN
F 1 "220" H 12400 4550 40 0000 C CNN
F 1 "FB" H 12400 4550 40 0000 C CNN
1 12400 4350
1 0 0 -1
$EndComp

View File

@@ -1,15 +1,15 @@
.data
;don't anger the stack!
dirptr_addr .word 0
dirptr_bank .byt 0
dirptr_bank .word 0
dirstart_addr .word 0
dirstart_bank .byt 0
dirend_addr .word 0
dirend_bank .byt 0
dirstart_bank .word 0
dirend_addr .word 0
dirend_bank .word 0
dirend_idx .word 0
dirptr_idx .word 0
dirent_addr .word 0
dirent_bank .byt 0
dirent_addr .word 0
dirent_bank .word 0
dirent_type .byt 0
dirend_onscreen .byt 0
dirlog_idx .byt 0,0,0 ; long ptr

View File

@@ -188,32 +188,26 @@ redraw_filelist_loop
lsr
cmp listdisp
beq redraw_filelist_last
lda dirptr_bank
phb
pha
plb
rep #$20 : .al
lda (dirptr_addr), y
lda [dirptr_addr], y
sta @dirent_addr
iny
iny
sep #$20 : .as
lda (dirptr_addr), y ; load fileinfo bank
lda [dirptr_addr], y ; load fileinfo bank
clc
adc #$c0 ; add $C0 for memory map
sta @dirent_bank ; store as current bank
cmp #$c0 ; if bank was 0 -> dirend entry in DB
beq redraw_filelist_dirend ; handle dirend
iny
lda (dirptr_addr), y
lda [dirptr_addr], y
iny
sta @dirent_type
plb
sty dirptr_idx
jsr print_direntry
bra redraw_filelist_loop
redraw_filelist_dirend
plb
dey ; recover last valid direntry number
dey ; (we had 2x iny of the direntry pointer above,
dey ; so account for those too)
@@ -225,15 +219,10 @@ redraw_filelist_dirend
sta dirend_onscreen
bra redraw_filelist_out
redraw_filelist_last ;check if next offscreen item is end of dir
lda dirptr_bank
phb
pha
plb
iny
iny
lda (dirptr_addr), y
lda [dirptr_addr], y
beq redraw_filelist_dirend
plb
redraw_filelist_out
ldx #$0000
stx dirptr_idx
@@ -352,7 +341,7 @@ menu_key_down:
lda listdisp
dec
cmp menu_sel
bne +
bne down_noscroll
lda #$01
sta menu_dirty
lda dirend_onscreen
@@ -361,10 +350,13 @@ menu_key_down:
lda dirptr_addr
clc
adc #$04
sta dirptr_addr
bcc +
inc dirptr_bank
+ sta dirptr_addr
sep #$20 : .as
rts
+ lda dirend_onscreen
down_noscroll
lda dirend_onscreen
beq +
lda dirend_idx
lsr
@@ -380,7 +372,7 @@ down_out
menu_key_up:
lda menu_sel
bne +
bne up_noscroll
lda #$01
sta menu_dirty
rep #$20 : .al
@@ -389,9 +381,12 @@ menu_key_up:
beq up_out
sec
sbc #$04
sta dirptr_addr
bcs +
dec dirptr_bank
+ sta dirptr_addr
bra up_out
+ dec
up_noscroll
dec
sta menu_sel
up_out
sep #$20 : .as
@@ -480,14 +475,10 @@ select_item:
asl
tay
sep #$20 : .as
lda dirptr_bank
phb
pha
plb
iny
iny
iny
lda (dirptr_addr), y
lda [dirptr_addr], y
cmp #$01
beq sel_is_file
cmp #$04
@@ -497,7 +488,6 @@ select_item:
cmp #$81
beq sel_is_parent
select_item_cont
plb
rts
sel_is_file
jsr select_file
@@ -513,12 +503,12 @@ select_file:
; have avr load the rom
dey
rep #$20 : .al
lda (dirptr_addr), y
lda [dirptr_addr], y
and #$00ff
sta @AVR_PARAM+2
dey
dey
lda (dirptr_addr), y
lda [dirptr_addr], y
sta @AVR_PARAM
sep #$20 : .as
lda #$01
@@ -559,14 +549,14 @@ select_dir:
; y = direntry ptr
txy
dey
lda (dirptr_addr), y
lda [dirptr_addr], y
clc
adc #$c0
sta @dirent_bank
dey
dey
rep #$20 : .al
lda (dirptr_addr), y
lda [dirptr_addr], y
sta @dirent_addr
tax
sep #$20 : .as

17
snes/tests/Makefile Normal file
View File

@@ -0,0 +1,17 @@
OBJS = header.ips reset.o65 tests.o65
all: test.bin
test.bin: $(OBJS)
sneslink -fsmc -o $@ $^
# Generic rule to create .o65 out from .a65
%.o65: %.a65
snescom -J -Wall -o $@ $<
# Generic rule to create .ips out from .a65
%.ips: %.a65
snescom -I -J -Wall -o $@ $<
clean:
rm -f *.ips *.o65 *~ test.bin

121
snes/tests/header.a65 Normal file
View File

@@ -0,0 +1,121 @@
; This file is part of the snescom-asm demo - a demo of how to build a SNES program.
; See http://bisqwit.iki.fi/source/snescom.html for details.
; Begin assembling to this address.
*= $C0F000
LINETEST:
sei
clc
xce
- lda $0000
lda $2100
sta $2100
bra -
*= $C0F100
IRQTEST:
sei
clc
xce
cli
sep #$20 : .as
rep #$10 : .xl
lda #$0f
sta $2100
lda #$ff
sta $4209
lda #$ff
sta $420a
lda #$ff
sta $4200
lda #$01
- sta @$002222
bra -
*= $C0F200
BANKTEST:
sei
clc
xce
sep #$20 : .as
lda #$01
sta @$0055aa
- bra -
*= $C0FF00
RESET:
sei
clc
xce
rep #$20 : .al
lda #$1fff
tcs
lda #$00
sta @$003333
jmp @GAME_MAIN
NMI_16bit:
php
rep #$30 : .al : .xl
pha: phx: phy: phd: phb
jsl @NMI_ROUTINE
rep #$30 : .al : .xl
int_exit:
plb: pld: ply: plx: pla
plp
rti
IRQ_16bit:
ABT_8bit: ABT_16bit:
php
rep #$30 : .al : .xl
pha: phx: phy: phd: phb
jsl @IRQ_ROUTINE
rep #$30 : .al : .xl
bra int_exit
;error vectors
BRK_8bit: BRK_16bit:
COP_8bit: COP_16bit:
IRQ_8bit:
NMI_8bit:
- wai: lda $ABCDEF : bra -
*= $C0FFB0
; Zero the area from $FFB0 - $FFFF
; to ensure that the linker won't get clever
; and fill it with small pieces of code.
.word 0,0,0,0, 0,0,0,0
.word 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
.word 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
*= $C0FFB0
.byt "MR" ;2 bytes - company id
.byt "TEST" ;4 bytes - rom id
*= $C0FFC0
.byt "SD2SNES TESTS "
;123456789012345678901; - max 21 chars
*= $C0FFD5 .byt $31 ;rom speed
*= $C0FFD6 .byt $02 ;rom type
*= $C0FFD7 .byt $06 ;rom size 64 kByte
*= $C0FFD8 .byt $03 ;sram size 8 kBit
*= $C0FFD9 .byt $09 ;rom region 4 = Finland
*= $C0FFDA .byt $33 ;company id flag
*= $C0FFDC .word 0,0 ;checksums
*= $C0FFE4 .word COP_16bit
*= $C0FFE6 .word BRK_16bit
*= $C0FFE8 .word ABT_16bit
*= $C0FFEA .word NMI_16bit
*= $C0FFEE .word IRQ_16bit
*= $C0FFF4 .word COP_8bit
*= $C0FFF8 .word ABT_8bit
*= $C0FFFA .word NMI_8bit
*= $C0FFFC .word RESET
*= $C0FFFE .word BRK_8bit
*= $C0FFFE .word IRQ_8bit

29
snes/tests/reset.a65 Normal file
View File

@@ -0,0 +1,29 @@
; This file is part of the snescom-asm demo - a demo of how to build a SNES program.
; See http://bisqwit.iki.fi/source/snescom.html for details.
; NMI - called on VBlank
NMI_ROUTINE:
sep #$20 : .as
rep #$10 : .xl
lda #$00
pha
plb
lda $4210 ; ack interrupt
rtl
; IRQ - called when triggered
IRQ_ROUTINE:
sep #$20 : .as
lda $4211 ;Acknowledge irq
lda #$00
sta @$002121
lda #$ff
sta @$002122
lda #$01
sta @$002122
lda #$5A
sta @$F00000
rtl

564
snes/tests/tests.a65 Normal file
View File

@@ -0,0 +1,564 @@
GAME_MAIN:
sep #$20 : .as
stz $4200 ; inhibit VBlank NMI
lda #$01
sta $420d ; fast cpu
jsr killdma
jsr waitblank
lda #$00
sta @$f00000
sta @$f00001
sta @$f00002
sta @$f00003
lda #$00
sta @$f01fff
jsr snes_init
jsr video_init
jsr linetest
jsr batest
jsr snes_init
jsr video_init
jsr copy_memtest
jsr irqtest
jsl $7e1800
- bra -
copy_memtest:
rep #$30 : .al : .xl
lda #$0300
ldx #!memtest
ldy #$1800
mvn $7e, ^memtest
rts
linetest
sep #$20 : .as
lda #$00
pha
plb
- lda $0000
lda $2100
sta $21ff
lda @$f01fff
cmp #$01
bne -
rts
irqtest:
cli
sep #$20 : .as
rep #$10 : .xl
lda #$0f
sta $2100
lda #$ff
sta $4209
lda #$ff
sta $420a
lda #$ff
sta $4200
sta @$f00000
lda #$01
sta @$002222
rts
batest:
sei
sep #$20 : .as
rep #$10 : .xl
lda #$00
ldx #$2100
- sta !$0, x
inx
inc
bne -
lda #$e0
pha
plb
lda #$00
ldx #$0000
- cmp !$0, x
bne batest_fail
inx
inc
bne -
lda #$5a
sta @$f00002
lda #$00
pha
plb
rts
batest_fail:
lda #$ff
sta @$f00002
lda #$00
pha
plb
rts
memtest:
; test 4 areas: 00-3f:8000-ffff
; 40-7d:0000-ffff
; 80-bf:8000-ffff
; 80-ff:0000-ffff
sep #$20 : .as
rep #$10 : .xl
lda #$01
sta @$003333 ; switch to linear memory mode
ldx #$8000
stx $00
ldx #$8000
stx $10
lda #$00
sta $03 ; bank no.
mem0_writeloop0:
; switch bank
pha
plb
lda #$01
sta @$003333
- lda $03
clc
adc $01
clc
adc $00
sta !$0000, x
inx
stx $00
bne -
ldx $10
inc $03
lda #$00
sta @$003333
lda $03
sta @$f00003
cmp #$40
bne mem0_writeloop0
ldx #$0000
stx $10
mem0_writeloop1:
; switch bank
lda #$01
sta @$003333
lda $03
pha
plb
- lda $03
clc
adc $01
clc
adc $00
sta !$0000, x
inx
stx $00
bne -
ldx $10
inc $03
lda #$00
sta @$003333
lda $03
sta @$f00003
cmp #$7e
bne mem0_writeloop1
ldx #$8000
stx $10
lda #$80
sta $03 ; bank no.
mem0_writeloop2:
; switch bank
lda #$01
sta @$003333
lda $03
pha
plb
- lda $03
clc
adc $01
clc
adc $00
sta !$0000, x
inx
stx $00
bne -
ldx $10
inc $03
lda #$00
sta @$003333
lda $03
sta @$f00003
cmp #$c0
bne mem0_writeloop2
ldx #$0000
stx $10
mem0_writeloop3:
; switch bank
lda #$01
sta @$003333
lda $03
pha
plb
- lda $03
clc
adc $01
clc
adc $00
sta !$0000, x
inx
stx $00
bne -
ldx $10
inc $03
lda #$00
sta @$003333
lda $03
sta @$f00003
bne mem0_writeloop3
lda #$00
sta @$002121
lda #$ff
sta @$002122
lda #$03
sta @$002122
ldx #$8000
stx $00
ldx #$8000
stx $10
lda #$00
sta $03 ; bank no.
mem0_verifyloop0:
; switch bank
lda #$01
sta @$f00001
lda #$01
sta @$003333
lda $03
pha
plb
- lda $03
clc
adc $01
clc
adc $00
cmp !$0000, x
bne mem0_fail
inx
stx $00
bne -
ldx $10
inc $03
lda #$00
sta @$003333
lda $03
sta @$f00003
cmp #$40
bne mem0_verifyloop0
ldx #$0000
stx $10
mem0_verifyloop1:
; switch bank
lda #$01
sta @$003333
lda $03
pha
plb
- lda $03
clc
adc $01
clc
adc $00
cmp !$0000, x
bne mem0_fail
inx
stx $00
bne -
ldx $10
inc $03
lda #$00
sta @$003333
lda $03
sta @$f00003
cmp #$7e
bne mem0_verifyloop1
ldx #$8000
stx $10
lda #$80
sta $03 ; bank no.
bra mem0_verifyloop2
mem0_fail:
lda #$00
pha
plb
sta @$003333
rep #$20 : .al
lda $00
sta @$f00004
sep #$20 : .as
lda $03
sta @$f00006
lda #$ff
sta @$f00001
rtl
mem0_verifyloop2:
; switch bank
lda #$01
sta @$003333
lda $03
pha
plb
- lda $03
clc
adc $01
clc
adc $00
cmp !$0000, x
bne mem0_fail
inx
stx $00
bne -
ldx $10
inc $03
lda #$00
sta @$003333
lda $03
sta @$f00003
cmp #$c0
bne mem0_verifyloop2
ldx #$0000
stx $10
mem0_verifyloop3:
; switch bank
lda #$01
sta @$003333
lda $03
pha
plb
- lda $03
clc
adc $01
clc
adc $00
cmp !$0000, x
bne mem0_fail
inx
stx $00
bne -
ldx $10
inc $03
lda #$00
sta @$003333
lda $03
sta @$f00003
bne mem0_verifyloop3
lda #$00
sta @$002121
lda #$e0
sta @$002122
lda #$03
sta @$002122
lda #$00
pha
plb
sta @$003333
lda #$5a
sta @$f00001
rtl
rtl
rtl
rtl
rtl
rtl
killdma:
stz $420b
stz $420c
stz $4310
stz $4311
stz $4312
stz $4313
stz $4314
stz $4320
stz $4321
stz $4322
stz $4323
stz $4324
stz $4330
stz $4331
stz $4332
stz $4333
stz $4334
stz $4340
stz $4341
stz $4342
stz $4343
stz $4344
stz $4350
stz $4351
stz $4352
stz $4353
stz $4354
stz $4360
stz $4361
stz $4362
stz $4363
stz $4364
rts
waitblank:
- lda $4212
and #$80
bne -
- lda $4212
and #$80
beq -
rts
video_init:
sep #$20 : .as ;8-bit accumulator
rep #$10 : .xl ;16-bit index
lda #$03 ;mode 3, mode 5 via HDMA :D
sta $2105
lda #$58 ;Tilemap addr 0xB000
ora #$02 ;SC size 32x64
sta $2107 ;for BG1
lda #$50 ;Tilemap addr 0xA000
ora #$02 ;SC size 32x64
sta $2108 ;for BG2
lda #$40 ;chr base addr:
sta $210b ;BG1=0x0000, BG2=0x8000
lda #$01 ;cut off leftmost subscreen pixel garbage
sta $2126
lda #$fe
sta $2127
lda #$10
sta $2130
lda #$1f
sta $212e
sta $212f
stz $2121
lda #$0f
sta $2100 ;screen on, full brightness
stz $2121
lda #$1f ;red background
sta $2122
stz $2122
rts
snes_init:
sep #$20 : .as ;8-bit accumulator
rep #$10 : .xl ;16-bit index
stz $4200 ;
lda #$ff
sta $4201 ;
stz $4202 ;
stz $4203 ;
stz $4204 ;
stz $4205 ;
stz $4206 ;
stz $4207 ;
stz $4208 ;
stz $4209 ;
stz $420a ;
stz $420b ;
stz $420c ;
lda #$8f
sta $2100 ;INIDISP: force blank
lda #$03 ; 8x8+16x16; name=0; base=3
sta $2101 ;
stz $2102 ;
stz $2103 ;
; stz $2104 ; (OAM Data?!)
; stz $2104 ; (OAM Data?!)
stz $2105 ;
stz $2106 ;
stz $2107 ;
stz $2108 ;
stz $2109 ;
stz $210a ;
stz $210b ;
stz $210c ;
stz $210d ;
stz $210d ;
stz $210e ;
stz $210e ;
stz $210f ;
stz $210f ;
lda #$05
sta $2110 ;
stz $2110 ;
stz $2111 ;
stz $2111 ;
stz $2112 ;
stz $2112 ;
stz $2113 ;
stz $2113 ;
stz $2114 ;
stz $2114 ;
lda #$80
sta $2115 ;
stz $2116 ;
stz $2117 ;
; stz $2118 ;(VRAM Data?!)
; stz $2119 ;(VRAM Data?!)
stz $211a ;
stz $211b ;
lda #$01
sta $211b ;
stz $211c ;
stz $211c ;
stz $211d ;
stz $211d ;
stz $211e ;
sta $211e ;
stz $211f ;
stz $211f ;
stz $2120 ;
stz $2120 ;
stz $2121 ;
; stz $2122 ; (CG Data?!)
; stz $2122 ; (CG Data?!)
stz $2123 ;
stz $2124 ;
stz $2125 ;
stz $2126 ;
stz $2127 ;
stz $2128 ;
stz $2129 ;
stz $212a ;
stz $212b ;
stz $212c ;
stz $212d ;
stz $212e ;
stz $212f ;
lda #$30
sta $2130 ;
stz $2131 ;
lda #$e0
sta $2132 ;
stz $2133 ;
;clear WRAM lower page
; ldx #$0200
; stx $2181
; lda #$00
; sta $2183
; DMA0(#$08, #$FF00, #^zero, #!zero, #$80)
; ldx #$0000
; stx $2181
; lda #$00
; sta $2183
; DMA0(#$08, #$1e0, #^zero, #!zero, #$80)
rts

View File

@@ -213,6 +213,8 @@ sym: $(TARGET).sym
# utils/lpcchksum $(TARGET).bin
fresh: erase program
program: bin
openocd -f openocd-usb.cfg -f lpc1754.cfg -f flash.cfg

View File

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

View File

@@ -1,7 +1,7 @@
#ifndef _CONFIG_H
#define _CONFIG_H
#define DEBUG_BL
//#define DEBUG_BL
// #define DEBUG_SD
// #define DEBUG_IRQ
@@ -19,7 +19,7 @@
#define DBG_BL while(0)
#endif
#define FW_START (0x00003000L)
#define FW_START (0x00002000L)
#define FLASH_SECTORS (17)
@@ -51,12 +51,12 @@
#define CONFIG_UART_NUM 3
// #define CONFIG_CPU_FREQUENCY 90315789
#define CONFIG_CPU_FREQUENCY (92000000L)
#define CONFIG_CPU_FREQUENCY (96000000L)
//#define CONFIG_CPU_FREQUENCY 46000000
#define CONFIG_UART_PCLKDIV 1
#define CONFIG_UART_TX_BUF_SHIFT 8
#define CONFIG_UART_BAUDRATE 921600
#define CONFIG_UART_DEADLOCKABLE
//#define CONFIG_UART_DEADLOCKABLE
#define SSP_CLK_DIVISOR_FAST 2
#define SSP_CLK_DIVISOR_SLOW 250

View File

@@ -183,7 +183,7 @@ FLASH_RES flash_file(uint8_t *filename) {
return ERR_FLASH;
}
}
if(total_read != file_header.size) {
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_UART uart_putc('X');
return ERR_FILECHK;

View File

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

View File

@@ -29,7 +29,7 @@ int main(void) {
SNES_CIC_PAIR_REG->FIODIR = BV(SNES_CIC_PAIR_BIT);
BITBAND(SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT) = 1;
/* LPC_GPIO2->FIODIR = BV(0) | BV(1) | BV(2); */
LPC_GPIO0->FIODIR = BV(16);
// LPC_GPIO0->FIODIR = BV(16);
/* connect UART3 on P0[25:26] + SSP0 on P0[15:18] + MAT3.0 on P0[10] */
LPC_PINCON->PINSEL1 = BV(18) | BV(19) | BV(20) | BV(21) /* UART3 */
@@ -50,7 +50,7 @@ int main(void) {
writeled(0);
/* do this last because the peripheral init()s change PCLK dividers */
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();
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);
@@ -61,7 +61,8 @@ DBG_BL printf("PCONP=%lx\n", LPC_SC->PCONP);
LPC_TIM3->MCR=MR0R;
LPC_TIM3->MR0=1;
LPC_TIM3->TCR=1;
NVIC->ICER[0] = 0xffffffff;
NVIC->ICER[1] = 0xffffffff;
FLASH_RES res = flash_file((uint8_t*)"/sd2snes/firmware.img");
if(res == ERR_FLASHPREP || res == ERR_FLASHERASE || res == ERR_FLASH) {
rdyled(0);

View File

@@ -10,7 +10,7 @@
#include "uart.h"
#include "led.h"
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,
133,143,154,167,182,200,214,222,231,
250,267,273,286,300,308,333,357,364,
@@ -45,8 +45,8 @@ static uint8_t uart_lookupratio(float f_fr) {
}
return ratios[i_result];
}
static uint32_t baud2divisor(unsigned int baudrate) {
*/
/*static uint32_t baud2divisor(unsigned int baudrate) {
uint32_t int_ratio;
uint32_t error;
uint32_t dl=0;
@@ -73,7 +73,7 @@ static uint32_t baud2divisor(unsigned int baudrate) {
return ((fract_ratio<<16)&0xff0000) | dl;
}
}
*/
static char txbuf[1 << CONFIG_UART_TX_BUF_SHIFT];
static volatile unsigned int read_idx,write_idx;
@@ -170,7 +170,7 @@ void uart_init(void) {
/* set baud rate - no fractional stuff for now */
UART_REGS->LCR = BV(7) | 3; // always 8n1
div = baud2divisor(CONFIG_UART_BAUDRATE);
div = 0x850004; // baud2divisor(CONFIG_UART_BAUDRATE);
UART_REGS->DLL = div & 0xff;
UART_REGS->DLM = (div >> 8) & 0xff;

View File

@@ -58,8 +58,8 @@ static char *curchar;
/* Word lists */
static char command_words[] =
"cd\0reset\0sreset\0dir\0ls\0test\0resume\0loadrom\0loadraw\0saveraw\0put\0d4\0vmode\0mapper\0settime\0time\0setfeature\0hexdump\0w8\0w16\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_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME, CMD_SETFEATURE, CMD_HEXDUMP, CMD_W8, CMD_W16 };
"cd\0reset\0sreset\0dir\0ls\0test\0resume\0loadrom\0loadraw\0saveraw\0put\0rm\0d4\0vmode\0mapper\0settime\0time\0setfeature\0hexdump\0w8\0w16\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_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME, CMD_SETFEATURE, CMD_HEXDUMP, CMD_W8, CMD_W16 };
/* ------------------------------------------------------------------------- */
/* Parse functions */
@@ -343,6 +343,11 @@ void cmd_put(void) {
}
}
void cmd_rm(void) {
FRESULT res = f_unlink(curchar);
if(res) printf("Error %d removing %s\n", res, curchar);
}
void cmd_mapper(void) {
int32_t mapper;
mapper = parse_unsigned(0,7,10);
@@ -509,6 +514,10 @@ void cli_loop(void) {
cmd_saveraw();
break;
case CMD_RM:
cmd_rm();
break;
case CMD_D4:
cmd_d4();
break;

View File

@@ -1,3 +1,4 @@
CONFIG_VERSION=0.0.1
CONFIG_FWVER=16777214
CONFIG_VERSION=0.1.1
#FWVER=000101
CONFIG_FWVER=257
CONFIG_MCU_FOSC=12000000

View File

@@ -65,8 +65,8 @@
#define FPGA_MCU_RDY_REG LPC_GPIO2
#define FPGA_MCU_RDY_BIT 9
#define QSORT_MAXELEM 1024
#define QSORT_MAXELEM 2048
#define CLTBL_SIZE 100
#define SSP_REGS LPC_SSP0
#define SSP_PCLKREG PCLKSEL1
// 1: PCLKSEL0

View File

@@ -2198,7 +2198,6 @@ FRESULT f_read (
#if !_FS_TINY
#if !_FS_READONLY
if (fp->flag & FA__DIRTY) { /* Write sector I/O buffer if needed */
printf("DIRTY!?!\n");
if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
ABORT(fp->fs, FR_DISK_ERR);
fp->flag &= ~FA__DIRTY;
@@ -2222,7 +2221,6 @@ printf("DIRTY!?!\n");
mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */
#else
mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */
printf("final mem_cpy, rcnt=%d, rbuff-buff=%d\n", rcnt, (void*)rbuff-buff);
} else {
sd_offload_partial_start = fp->fptr % SS(fp->fs);
sd_offload_partial_end = sd_offload_partial_start + rcnt;
@@ -2376,7 +2374,6 @@ FRESULT f_sync (
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (res == FR_OK) {
if (fp->flag & FA__WRITTEN) { /* Has the file been written? */
printf("DIRTY?!?!?!\n");
#if !_FS_TINY /* Write-back dirty buffer */
if (fp->flag & FA__DIRTY) {
if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
@@ -2822,6 +2819,46 @@ FRESULT f_readdir (
}
FRESULT l_opendirbycluster (
FATFS *fs,
DIR *dj,
const TCHAR *path,
DWORD clust
)
{
FRESULT res;
res = chk_mounted(&path, &fs, 0);
DEF_NAMEBUF;
INIT_BUF(*dj);
dj->sclust = clust;
dj->fs = fs;
dj->id = fs->id;
dj->dir = 0;
res = dir_sdi(dj, 0);
FREE_BUF();
return res;
}
FRESULT l_openfilebycluster (
FATFS *fs, /* Pointer to file system object */
FIL *fp, /* Pointer to the blank file object */
const TCHAR *path,
DWORD clust, /* Cluster number to be opened */
DWORD fsize /* File size to be assumed */
)
{
chk_mounted(&path, &fs, 0);
fp->flag = FA_READ;
fp->org_clust = clust;
fp->fsize = fsize;
fp->fptr = 0;
fp->dsect = 0;
fp->fs = fs;
return FR_OK;
}
#if _FS_MINIMIZE == 0
/*-----------------------------------------------------------------------*/
@@ -2854,27 +2891,6 @@ FRESULT f_stat (
LEAVE_FF(dj.fs, res);
}
FRESULT l_openfilebycluster (
FATFS *fs, /* Pointer to file system object */
FIL *fp, /* Pointer to the blank file object */
const TCHAR *path,
DWORD clust, /* Cluster number to be opened */
DWORD fsize /* File size to be assumed */
)
{
chk_mounted(&path, &fs, 0);
fp->flag = FA_READ;
fp->org_clust = clust;
fp->fsize = fsize;
fp->fptr = 0;
fp->dsect = 0;
fp->fs = fs;
return FR_OK;
}
#if !_FS_READONLY
/*-----------------------------------------------------------------------*/
/* Get Number of Free Clusters */

View File

@@ -398,6 +398,7 @@ typedef enum {
/* 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_opendirbycluster (FATFS *fs, DIR *dj, const TCHAR *path, DWORD clust);
/* application level functions */
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */

View File

@@ -48,7 +48,7 @@
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */
#define _USE_FASTSEEK 1 /* 0:Disable or 1:Enable */
/* To enable fast seek feature, set _USE_FASTSEEK to 1. */

View File

@@ -47,6 +47,10 @@ void file_reinit(void) {
file_init();
}
FRESULT dir_open_by_filinfo(DIR* dir, FILINFO* fno) {
return l_opendirbycluster(&fatfs, dir, (TCHAR*)"", fno->clust);
}
void file_open_by_filinfo(FILINFO* fno) {
file_res = l_openfilebycluster(&fatfs, &file_handle, (TCHAR*)"", fno->clust, fno->fsize);
}

View File

@@ -41,6 +41,7 @@ enum filestates file_status;
void file_init(void);
void file_open(uint8_t* filename, BYTE flags);
FRESULT dir_open_by_filinfo(DIR* dir, FILINFO* fno_param);
void file_open_by_filinfo(FILINFO* fno);
void file_close(void);
void file_seek(uint32_t offset);

View File

@@ -53,7 +53,7 @@ uint16_t scan_flat(const char* path) {
return numentries;
}
uint32_t scan_dir(char* path, 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;
FILINFO fno;
FRESULT res;
@@ -97,13 +97,17 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
if(next_subdir_tgt > dir_end) {
dir_end = next_subdir_tgt;
}
printf("path=%s depth=%d ptr=%lx entries=%d parent=%lx next subdir @%lx\n", path, depth, db_tgt, numentries, parent_tgt, next_subdir_tgt);
// printf("path=%s depth=%d ptr=%lx entries=%d parent=%lx next subdir @%lx\n", path, depth, db_tgt, numentries, parent_tgt, next_subdir_tgt);
if(mkdb) {
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);
}
}
res = f_opendir(&dir, (TCHAR*)path);
if(fno_param) {
res = dir_open_by_filinfo(&dir, fno_param);
} else {
res = f_opendir(&dir, path);
}
if (res == FR_OK) {
if(pass && parent_tgt && mkdb) {
/* write backlink to parent dir
@@ -114,6 +118,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
db_tgt += 0x00010000;
printf("new=%lx\n", 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_writebyte(0, db_tgt+sizeof(next_subdir_tgt));
sram_writeblock("../\0", db_tgt+sizeof(next_subdir_tgt)+sizeof(len), 4);
@@ -142,9 +147,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
if(mkdb) {
uint16_t pathlen = strlen(path);
/* write element pointer to current dir structure */
printf("d=%d Saving %lx to Address %lx [dir]\n", depth, db_tgt, dir_tgt);
sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x80<<24), dir_tgt);
// printf("d=%d Saving %lx to Address %lx [dir]\n", depth, db_tgt, dir_tgt);
/* save element:
- path name
- pointer to sub dir structure */
@@ -154,7 +157,12 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
db_tgt += 0x00010000;
printf("new=%lx\n", db_tgt);
}
printf(" Saving dir descriptor to %lx tgt=%lx, path=%s\n", db_tgt, next_subdir_tgt, path);
// printf(" Saving dir descriptor to %lx tgt=%lx, path=%s\n", db_tgt, next_subdir_tgt, path);
/* write element pointer to current dir structure */
sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x80<<24), dir_tgt);
/* save element:
- path name
- pointer to sub dir structure */
sram_writelong((next_subdir_tgt-SRAM_MENU_ADDR), db_tgt);
sram_writebyte(len+1, db_tgt+sizeof(next_subdir_tgt));
sram_writeblock(path, db_tgt+sizeof(next_subdir_tgt)+sizeof(len), pathlen);
@@ -162,7 +170,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
db_tgt += sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2;
}
parent_tgt = this_dir_tgt;
scan_dir(path, mkdb, next_subdir_tgt);
scan_dir(path, &fno, mkdb, next_subdir_tgt);
dir_tgt += 4;
was_empty = 0;
}

View File

@@ -50,7 +50,7 @@ char fs_path[256];
SNES_FTYPE determine_filetype(char* filename);
//uint32_t scan_fs();
uint16_t scan_flat(const char* path);
uint32_t scan_dir(char* path, char mkdb, uint32_t this_subdir_tgt);
uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_subdir_tgt);
FRESULT get_db_id(uint32_t*);
int get_num_dirent(uint32_t addr);
void sort_all_dir(uint32_t endaddr);

View File

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

View File

@@ -133,6 +133,7 @@
#include "spi.h"
#include "fpga_spi.h"
#include "timer.h"
#include "sdnative.h"
void fpga_spi_init(void) {
spi_init(SPI_SPEED_FAST);
@@ -230,10 +231,12 @@ void fpga_sddma(uint8_t tgt, uint8_t partial) {
FPGA_SELECT();
FPGA_TX_BYTE(0xF1); /* STATUS */
FPGA_TX_BYTE(0x00); /* dummy */
DBG_SD printf("FPGA DMA request sent, wait for completion...");
while((status=FPGA_RX_BYTE()) & 0x80) {
FPGA_RX_BYTE(); /* eat the 2nd status byte */
test++;
}
DBG_SD printf("...complete\n");
FPGA_DESELECT();
if(test<5)printf("loopy: %ld %02x\n", test, status);
BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1;

View File

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

View File

@@ -145,7 +145,7 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id) || (newcard)) {
newcard = 0;
/* generate fs footprint (interesting files only) */
uint32_t curr_dir_id = scan_dir(fs_path, 0, 0);
uint32_t curr_dir_id = scan_dir(fs_path, NULL, 0, 0);
printf("curr dir id = %lx\n", curr_dir_id);
/* files changed or no database found? */
if((get_db_id(&saved_dir_id) != FR_OK)
@@ -154,7 +154,7 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
printf("saved dir id = %lx\n", saved_dir_id);
printf("rebuilding database...");
snes_bootprint(" rebuilding database ... \0");
curr_dir_id = scan_dir(fs_path, 1, 0);
curr_dir_id = scan_dir(fs_path, NULL, 1, 0);
sram_writeblock(&curr_dir_id, SRAM_DB_ADDR, 4);
uint32_t endaddr, direndaddr;
sram_readblock(&endaddr, SRAM_DB_ADDR+4, 4);

View File

@@ -34,7 +34,7 @@
#define SRAM_SAVE_ADDR (0xE00000L)
#define SRAM_MENU_ADDR (0xE00000L)
#define SRAM_DB_ADDR (0xE20000L)
#define SRAM_DB_ADDR (0xE40000L)
#define SRAM_DIR_ADDR (0xE10000L)
#define SRAM_CMD_ADDR (0xFF1000L)
#define SRAM_PARAM_ADDR (0xFF1004L)

View File

@@ -13,6 +13,9 @@
#include "smc.h"
FIL msufile;
DWORD msu_cltbl[CLTBL_SIZE] IN_AHBRAM;
DWORD pcm_cltbl[CLTBL_SIZE] IN_AHBRAM;
extern snes_romprops_t romprops;
int msu1_check_reset(void) {
@@ -40,6 +43,11 @@ int msu1_check(uint8_t* filename) {
printf("MSU datafile not found\n");
return 0;
}
msufile.cltbl = msu_cltbl;
msu_cltbl[0] = CLTBL_SIZE;
if(f_lseek(&msufile, CREATE_LINKMAP)) {
printf("Error creating FF linkmap for MSU file!\n");
}
romprops.fpga_features |= FEAT_MSU1;
return 1;
}
@@ -128,6 +136,9 @@ int msu1_loop() {
strcpy(strrchr((char*)file_buf, (int)'.'), suffix);
printf("filename: %s\n", file_buf);
f_open(&file_handle, (const TCHAR*)file_buf, FA_READ);
file_handle.cltbl = pcm_cltbl;
pcm_cltbl[0] = CLTBL_SIZE;
f_lseek(&file_handle, CREATE_LINKMAP);
f_lseek(&file_handle, 4L);
f_read(&file_handle, &msu_loop_point, 4, &bytes_read);
printf("loop point: %ld samples\n", msu_loop_point);

View File

@@ -449,9 +449,11 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
j=datcnt;
datshift=8;
DBG_SD printf("response over, waiting for data...\n");
/* wait for data start bit on DAT0 */
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
wiggle_fast_neg1();
}
DBG_SD if(!timeout) printf("timed out!\n");
wiggle_fast_neg1(); /* eat the start bit */
if(sd_offload) {
if(sd_offload_partial) {
@@ -588,9 +590,12 @@ int stream_datablock(uint8_t *buf) {
uint8_t datdata=0;
uint32_t timeout=1000000;
DBG_SD printf("stream_datablock: wait for ready...\n");
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
wiggle_fast_neg1();
}
DBG_SD if(!timeout) printf("timeout!\n");
wiggle_fast_neg1(); /* eat the start bit */
if(sd_offload) {
if(sd_offload_partial) {
@@ -867,6 +872,9 @@ DRESULT sdn_initialize(BYTE drv) {
if(rsp[1]&0x80) break;
}
BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0;
BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
ccs = (rsp[1]>>6) & 1; /* SDHC/XC */
cmd_slow(ALL_SEND_CID, 0, 0x4d, NULL, rsp);

318
src/tests/Makefile Normal file
View File

@@ -0,0 +1,318 @@
# Hey Emacs, this is a -*- makefile -*-
#----------------------------------------------------------------------------
# WinAVR Makefile Template written by Eric B. Weddington, Joerg Wunsch, et al.
#
# Released to the Public Domain
#
# Additional material for this makefile was written by:
# Peter Fleury
# Tim Henigan
# Colin O'Flynn
# Reiner Patommel
# Markus Pfaff
# Sander Pool
# Frederik Rouleau
# Carlos Lamas
#
#
# Extensively modified for sd2iec and later adapted for ARM by Ingo Korb
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------
# Read configuration file
ifdef CONFIG
CONFIGSUFFIX = $(CONFIG:config%=%)
else
CONFIG = config
CONFIGSUFFIX =
endif
# Enable verbose compilation with "make V=1"
ifdef V
Q :=
E := @:
else
Q := @
E := @echo
endif
# Include the configuration file
include $(CONFIG)
# Directory for all generated files
OBJDIR := obj$(CONFIGSUFFIX)
# Output format. (can be srec, ihex, binary)
FORMAT = binary
# Linker script
LINKERSCRIPT = lpc1754.ld
# Target file name (without extension).
TARGET = $(OBJDIR)/sd2snes
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c ff.c ccsbcs.c clock.c uart.c power.c led.c timer.c printf.c spi.c fileops.c rtc.c fpga.c fpga_spi.c snes.c smc.c memory.c filetypes.c faulthandler.c sort.c crc32.c cic.c cli.c xmodem.c irq.c rle.c sdnative.c msu1.c crc16.c tests.c
# usbcontrol.c usb_hid.c usbhw_lpc.c usbinit.c usbstdreq.c
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC = startup.S crc.S
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
# Use s -mcall-prologues when you really need size...
#OPT = 2
OPT = 2
# Debugging format.
DEBUG = dwarf-2
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS =
# Compiler flag to set the C Standard level.
# c89 = "ANSI" C
# gnu89 = c89 plus GCC extensions
# c99 = ISO C99 standard (not yet fully implemented)
# gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu99
# Place -D or -U options here
CDEFS = -DF_OSC=$(CONFIG_MCU_FOSC)UL
# Place -I options here
CINCS =
# CPU-specific flags
ifndef CPUFLAGS
CPUFLAGS := -mthumb -mcpu=cortex-m3
endif
ifndef ARCH
ARCH := arm-none-eabi
endif
# Define programs and commands.
# CC must be defined here to generate the correct CFLAGS
SHELL = sh
CC = $(ARCH)-gcc
OBJCOPY = $(ARCH)-objcopy
OBJDUMP = $(ARCH)-objdump
SIZE = $(ARCH)-size
NM = $(ARCH)-nm
REMOVE = rm -f
COPY = cp
AWK = awk
#---------------- Compiler Options ----------------
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS) $(CINCS)
CFLAGS += -O$(OPT)
CFLAGS += $(CPUFLAGS) -nostartfiles
#CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wstrict-prototypes -Werror
CFLAGS += -Wa,-adhlns=$(OBJDIR)/$(<:.c=.lst)
CFLAGS += -I$(OBJDIR)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
CFLAGS += -ffunction-sections -fdata-sections
#---------------- Assembler Options ----------------
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
ASFLAGS = $(CPUFLAGS) -Wa,-adhlns=$(OBJDIR)/$(<:.S=.lst),-gstabs -I$(OBJDIR)
#---------------- Linker Options ----------------
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += -T$(LINKERSCRIPT)
LDFLAGS += -Wl,--gc-sections
ifeq ($(CONFIG_LINKER_RELAX),y)
LDFLAGS += -Wl,-O9,--relax
endif
#============================================================================
# De-dupe the list of C source files
CSRC := $(sort $(SRC))
# Define all object files.
OBJ := $(patsubst %,$(OBJDIR)/%,$(CSRC:.c=.o) $(ASRC:.S=.o))
# Define all listing files.
LST := $(patsubst %,$(OBJDIR)/%,$(CSRC:.c=.lst) $(ASRC:.S=.lst))
# Compiler flags to generate dependency files.
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -I. -x assembler-with-cpp $(ASFLAGS) $(CDEFS)
# Default target.
all: build
build: elf bin hex
$(E) " SIZE $(TARGET).elf"
$(Q)$(ELFSIZE)|grep -v debug
cp $(TARGET).bin $(OBJDIR)/firmware.img
utils/genhdr $(OBJDIR)/firmware.img SNSD $(CONFIG_FWVER)
elf: $(TARGET).elf
bin: $(TARGET).bin
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
# # A little helper target for the maintainer =)
# copy2card:
# cp $(TARGET).bin /mbed/hw_LPC1768.bin
program: build
utils/lpcchksum $(TARGET).bin
openocd -f openocd-usb.cfg -f lpc1754.cfg -f flash.cfg
debug: build
openocd -f openocd-usb.cfg -f lpc1754.cfg
reset:
openocd -f openocd-usb.cfg -f lpc1754.cfg -f reset.cfg
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -A $(TARGET).elf
# Generate autoconf.h from config
.PRECIOUS : $(OBJDIR)/autoconf.h
$(OBJDIR)/autoconf.h: $(CONFIG) | $(OBJDIR)
$(E) " CONF2H $(CONFIG)"
$(Q)$(AWK) -f conf2h.awk $(CONFIG) > $(OBJDIR)/autoconf.h
# Create final output files from ELF output file.
$(OBJDIR)/%.bin: $(OBJDIR)/%.elf
$(E) " BIN $@"
$(Q)$(OBJCOPY) -O binary $< $@
$(OBJDIR)/%.hex: $(OBJDIR)/%.elf
$(E) " HEX $@"
$(Q)$(OBJCOPY) -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
$(OBJDIR)/%.lss: $(OBJDIR)/%.elf
$(E) " LSS $<"
$(Q)$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
$(OBJDIR)/%.sym: $(OBJDIR)/%.elf
$(E) " SYM $<"
$(E)$(NM) -n $< > $@
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
$(TARGET).elf : $(OBJ)
$(E) " LINK $@"
$(Q)$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
# Compile: create object files from C source files.
$(OBJDIR)/%.o : %.c | $(OBJDIR) $(OBJDIR)/autoconf.h
$(E) " CC $<"
$(Q)$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
$(OBJDIR)/%.s : %.c | $(OBJDIR) $(OBJDIR)/autoconf.h
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
$(OBJDIR)/%.o : %.S | $(OBJDIR) $(OBJDIR)/autoconf.h
$(E) " AS $<"
$(Q)$(CC) -c $(ALL_ASFLAGS) $< -o $@
# Create preprocessed source for use in sending a bug report.
$(OBJDIR)/%.i : %.c | $(OBJDIR) $(OBJDIR)/autoconf.h
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@
# Create the output directory
$(OBJDIR) :
$(E) " MKDIR $(OBJDIR)"
$(Q)mkdir $(OBJDIR)
# Target: clean project.
clean: begin clean_list end
clean_list :
$(E) " CLEAN"
$(Q)$(REMOVE) $(TARGET).hex
$(Q)$(REMOVE) $(TARGET).bin
$(Q)$(REMOVE) $(TARGET).elf
$(Q)$(REMOVE) $(TARGET).map
$(Q)$(REMOVE) $(TARGET).sym
$(Q)$(REMOVE) $(TARGET).lss
$(Q)$(REMOVE) $(OBJ)
$(Q)$(REMOVE) $(OBJDIR)/autoconf.h
$(Q)$(REMOVE) $(OBJDIR)/*.bin
$(Q)$(REMOVE) $(LST)
$(Q)$(REMOVE) $(CSRC:.c=.s)
$(Q)$(REMOVE) $(CSRC:.c=.d)
$(Q)$(REMOVE) .dep/*
-$(Q)rmdir $(OBJDIR)
# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter \
build elf hex lss sym clean clean_list

21
src/tests/bits.h Normal file
View File

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

540
src/tests/ccsbcs.c Normal file
View File

@@ -0,0 +1,540 @@
/*------------------------------------------------------------------------*/
/* Unicode - Local code bidirectional converter (C)ChaN, 2009 */
/* (SBCS code pages) */
/*------------------------------------------------------------------------*/
/* 437 U.S. (OEM)
/ 720 Arabic (OEM)
/ 1256 Arabic (Windows)
/ 737 Greek (OEM)
/ 1253 Greek (Windows)
/ 1250 Central Europe (Windows)
/ 775 Baltic (OEM)
/ 1257 Baltic (Windows)
/ 850 Multilingual Latin 1 (OEM)
/ 852 Latin 2 (OEM)
/ 1252 Latin 1 (Windows)
/ 855 Cyrillic (OEM)
/ 1251 Cyrillic (Windows)
/ 866 Russian (OEM)
/ 857 Turkish (OEM)
/ 1254 Turkish (Windows)
/ 858 Multilingual Latin 1 + Euro (OEM)
/ 862 Hebrew (OEM)
/ 1255 Hebrew (Windows)
/ 874 Thai (OEM, Windows)
/ 1258 Vietnam (OEM, Windows)
*/
#include "../ff.h"
#if _CODE_PAGE == 437
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 720
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9,
0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642,
0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A,
0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0xO650, 0x2248,
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 737
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398,
0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9,
0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0,
0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD,
0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E,
0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248,
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 775
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107,
0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A,
0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6,
0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118,
0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D,
0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B,
0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144,
0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019,
0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E,
0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 850
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE,
0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 852
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7,
0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A,
0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E,
0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A,
0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE,
0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161,
0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4,
0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8,
0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 855
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404,
0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C,
0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414,
0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438,
0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E,
0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580,
0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443,
0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116,
0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D,
0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 857
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F,
0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE,
0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000,
0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 858
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
0x00A9, 0x2563, 0x2551, 0x2557, 0x2550, 0x00A2, 0x00A5, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE,
0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00C6, 0x00CC, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 862
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 866
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E,
0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 874
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07,
0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17,
0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F,
0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000
};
#elif _CODE_PAGE == 1250
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A,
0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B,
0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C,
0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
};
#elif _CODE_PAGE == 1251
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x0000, 0x2111, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457,
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F
};
#elif _CODE_PAGE == 1252
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178,
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
};
#elif _CODE_PAGE == 1253
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7,
0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
0x03A8, 0x03A9, 0x03AA, 0x03AD, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000
};
#elif _CODE_PAGE == 1254
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x0130, 0x015E, 0x00DF,
0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF
};
#elif _CODE_PAGE == 1255
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3,
0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000
};
#elif _CODE_PAGE == 1256
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA,
0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F,
0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7,
0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0640, 0x0642, 0x0643,
0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7,
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF,
0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7,
0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2
}
#elif _CODE_PAGE == 1257
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000,
0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7,
0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7,
0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113,
0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7,
0x0173, 0x014E, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9
};
#elif _CODE_PAGE == 1258
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF,
0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7,
0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF,
0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF,
0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7,
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF
};
#endif
#if !_TBLDEF || !_USE_LFN
#error This file is not needed in current configuration. Remove from the project.
#endif
WCHAR ff_convert ( /* Converted character, Returns zero on error */
WCHAR src, /* Character code to be converted */
UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
)
{
WCHAR c;
if (src < 0x80) { /* ASCII */
c = src;
} else {
if (dir) { /* OEMCP to Unicode */
c = (src >= 0x100) ? 0 : Tbl[src - 0x80];
} else { /* Unicode to OEMCP */
for (c = 0; c < 0x80; c++) {
if (src == Tbl[c]) break;
}
c = (c + 0x80) & 0xFF;
}
}
return c;
}
WCHAR ff_wtoupper ( /* Upper converted character */
WCHAR chr /* Input character */
)
{
static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 };
static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 };
int i;
for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ;
return tbl_lower[i] ? tbl_upper[i] : chr;
}

76
src/tests/cic.c Normal file
View File

@@ -0,0 +1,76 @@
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "bits.h"
#include "config.h"
#include "uart.h"
#include "cic.h"
char *cicstatenames[4] = { "CIC_OK", "CIC_FAIL", "CIC_PAIR", "CIC_SCIC" };
void print_cic_state() {
printf("CIC state: %s\n", get_cic_statename(get_cic_state()));
}
inline char *get_cic_statename(enum cicstates state) {
return cicstatenames[state];
}
enum cicstates get_cic_state() {
uint32_t count;
uint32_t togglecount = 0;
uint8_t state, state_old;
state_old = BITBAND(SNES_CIC_STATUS_REG->FIOPIN, SNES_CIC_STATUS_BIT);
/* this loop samples at ~10MHz */
for(count=0; count<CIC_SAMPLECOUNT; count++) {
state = BITBAND(SNES_CIC_STATUS_REG->FIOPIN, SNES_CIC_STATUS_BIT);
if(state != state_old) {
togglecount++;
}
state_old = state;
}
/* CIC_TOGGLE_THRESH_PAIR > CIC_TOGGLE_THRESH_SCIC */
if(togglecount > CIC_TOGGLE_THRESH_PAIR) {
return CIC_PAIR;
} else if(togglecount > CIC_TOGGLE_THRESH_SCIC) {
return CIC_SCIC;
} else if(state) {
return CIC_OK;
} else return CIC_FAIL;
}
void cic_init(int allow_pairmode) {
BITBAND(SNES_CIC_PAIR_REG->FIODIR, SNES_CIC_PAIR_BIT) = 1;
if(allow_pairmode) {
BITBAND(SNES_CIC_PAIR_REG->FIOCLR, SNES_CIC_PAIR_BIT) = 1;
} else {
BITBAND(SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT) = 1;
}
BITBAND(SNES_CIC_D0_REG->FIODIR, SNES_CIC_D0_BIT) = 0;
BITBAND(SNES_CIC_D1_REG->FIODIR, SNES_CIC_D1_BIT) = 0;
}
/* prepare GPIOs for pair mode + set initial modes */
void cic_pair(int init_vmode, int init_d4) {
cic_videomode(init_vmode);
cic_d4(init_d4);
BITBAND(SNES_CIC_D0_REG->FIODIR, SNES_CIC_D0_BIT) = 1;
BITBAND(SNES_CIC_D1_REG->FIODIR, SNES_CIC_D1_BIT) = 1;
}
void cic_videomode(int value) {
if(value) {
BITBAND(SNES_CIC_D0_REG->FIOSET, SNES_CIC_D0_BIT) = 1;
} else {
BITBAND(SNES_CIC_D0_REG->FIOCLR, SNES_CIC_D0_BIT) = 1;
}
}
void cic_d4(int value) {
if(value) {
BITBAND(SNES_CIC_D1_REG->FIOSET, SNES_CIC_D1_BIT) = 1;
} else {
BITBAND(SNES_CIC_D1_REG->FIOCLR, SNES_CIC_D1_BIT) = 1;
}
}

23
src/tests/cic.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef _CIC_H
#define _CIC_H
#define CIC_SAMPLECOUNT (100000)
#define CIC_TOGGLE_THRESH_PAIR (2500)
#define CIC_TOGGLE_THRESH_SCIC (10)
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "bits.h"
enum cicstates { CIC_OK = 0, CIC_FAIL, CIC_PAIR, CIC_SCIC };
enum cic_region { CIC_NTSC = 0, CIC_PAL };
void print_cic_state(void);
char *get_cic_statename(enum cicstates state);
enum cicstates get_cic_state(void);
void cic_init(int allow_pairmode);
void cic_pair(int init_vmode, int init_d4);
void cic_videomode(int value);
void cic_d4(int value);
#endif

576
src/tests/cli.c Normal file
View File

@@ -0,0 +1,576 @@
/* tapplay - TAP file playback for sd2iec hardware
Copyright (C) 2009 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
cli.c: The command line interface
*/
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include <arm/bits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include "config.h"
#include "diskio.h"
#include "ff.h"
#include "timer.h"
#include "uart.h"
#include "fileops.h"
#include "memory.h"
#include "snes.h"
#include "fpga.h"
#include "fpga_spi.h"
#include "cic.h"
#include "xmodem.h"
#include "rtc.h"
#include "cli.h"
#define MAX_LINE 250
/* Variables */
static char cmdbuffer[MAX_LINE+1];
static char *curchar;
/* Word lists */
static char command_words[] =
"cd\0reset\0sreset\0dir\0ls\0test\0resume\0loadrom\0loadraw\0saveraw\0put\0rm\0d4\0vmode\0mapper\0settime\0time\0setfeature\0hexdump\0w8\0w16\0memsel\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_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME, CMD_SETFEATURE, CMD_HEXDUMP, CMD_W8, CMD_W16, CMD_MEMSEL };
/* ------------------------------------------------------------------------- */
/* Parse functions */
/* ------------------------------------------------------------------------- */
/* Skip spaces at curchar */
static uint8_t skip_spaces(void) {
uint8_t res = (*curchar == ' ' || *curchar == 0);
while (*curchar == ' ')
curchar++;
return res;
}
/* 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) {
char *end;
uint32_t result;
if (strlen(curchar) == 1 && *curchar == '?') {
printf("Number between %ld[0x%lx] and %ld[0x%lx] expected\n",lower,lower,upper,upper);
return -2;
}
result = strtoul(curchar, &end, base);
if ((*end != ' ' && *end != 0) || errno != 0) {
printf("Invalid numeric argument\n");
return -1;
}
curchar = end;
skip_spaces();
if (result < lower || result > upper) {
printf("Numeric argument out of range (%ld..%ld)\n",lower,upper);
return -1;
}
return result;
}
/* Parse the string starting with curchar for a word in wordlist */
static int8_t parse_wordlist(char *wordlist) {
uint8_t i, matched;
char *cur, *ptr;
char c;
i = 0;
ptr = wordlist;
// Command list on "?"
if (strlen(curchar) == 1 && *curchar == '?') {
printf("Commands available: \n ");
while (1) {
c = *ptr++;
if (c == 0) {
if (*ptr == 0) {
printf("\n");
return -2;
} else {
printf("\n ");
}
} else
uart_putc(c);
}
}
while (1) {
cur = curchar;
matched = 1;
c = *ptr;
do {
// If current word list character is \0: No match found
if (c == 0) {
printf("Unknown word: %s\n",curchar);
return -1;
}
if (tolower(c) != tolower(*cur)) {
// Check for end-of-word
if (cur != curchar && (*cur == ' ' || *cur == 0)) {
// Partial match found, return that
break;
} else {
matched = 0;
break;
}
}
ptr++;
cur++;
c = *ptr;
} while (c != 0);
if (matched) {
char *tmp = curchar;
curchar = cur;
// Return match only if whitespace or end-of-string follows
// (avoids mismatching partial words)
if (skip_spaces()) {
return i;
} else {
printf("Unknown word: %s\n(use ? for help)\n",tmp);
return -1;
}
} else {
// Try next word in list
i++;
while (*ptr++ != 0) ;
}
}
}
/* Read a line from serial, uses cmdbuffer as storage */
static char *getline(char *prompt) {
int i=0;
char c;
printf("\n%s",prompt);
memset(cmdbuffer,0,sizeof(cmdbuffer));
while (1) {
c = uart_getc();
if (c == 13)
break;
if (c == 27 || c == 3) {
printf("\\\n%s",prompt);
i = 0;
memset(cmdbuffer,0,sizeof(cmdbuffer));
continue;
}
if (c == 127 || c == 8) {
if (i > 0) {
i--;
uart_putc(8); // backspace
uart_putc(' '); // erase character
uart_putc(8); // backspace
} else
continue;
} else {
if (i < sizeof(cmdbuffer)-1) {
cmdbuffer[i++] = c;
uart_putc(c);
}
}
}
cmdbuffer[i] = 0;
return cmdbuffer;
}
/* ------------------------------------------------------------------------- */
/* Command functions */
/* ------------------------------------------------------------------------- */
/* Reset */
static void cmd_reset(void) {
/* force watchdog reset */
LPC_WDT->WDTC = 256; // minimal timeout
LPC_WDT->WDCLKSEL = BV(31); // internal RC, lock register
LPC_WDT->WDMOD = BV(0) | BV(1); // enable watchdog and reset-by-watchdog
LPC_WDT->WDFEED = 0xaa;
LPC_WDT->WDFEED = 0x55; // initial feed to really enable WDT
}
/* Show the contents of the current directory */
static void cmd_show_directory(void) {
FRESULT res;
DIR dh;
FILINFO finfo;
uint8_t *name;
f_getcwd((TCHAR*)file_lfn, 255);
res = f_opendir(&dh, (TCHAR*)file_lfn);
if (res != FR_OK) {
printf("f_opendir failed, result %d\n",res);
return;
}
finfo.lfname = (TCHAR*)file_lfn;
finfo.lfsize = 255;
do {
/* Read the next entry */
res = f_readdir(&dh, &finfo);
if (res != FR_OK) {
printf("f_readdir failed, result %d\n",res);
return;
}
/* Abort if none was found */
if (!finfo.fname[0])
break;
/* Skip volume labels */
if (finfo.fattrib & AM_VOL)
continue;
/* Select between LFN and 8.3 name */
if (finfo.lfname[0])
name = (uint8_t*)finfo.lfname;
else {
name = (uint8_t*)finfo.fname;
strlwr((char *)name);
}
printf("%s",name);
/* Directory indicator (Unix-style) */
if (finfo.fattrib & AM_DIR)
uart_putc('/');
printf("\n");
} while (finfo.fname[0]);
}
static void cmd_loadrom(void) {
uint32_t address = 0;
uint8_t flags = LOADROM_WITH_SRAM | LOADROM_WITH_RESET;
load_rom((uint8_t*)curchar, address, flags);
}
static void cmd_loadraw(void) {
uint32_t address = parse_unsigned(0,16777216,16);
load_sram((uint8_t*)curchar, address);
}
static void cmd_saveraw(void) {
uint32_t address = parse_unsigned(0,16777216,16);
uint32_t length = parse_unsigned(0,16777216,16);
save_sram((uint8_t*)curchar, length, address);
}
static void cmd_d4(void) {
int32_t hz;
if(get_cic_state() != CIC_PAIR) {
printf("not in pair mode\n");
} else {
hz = parse_unsigned(50,60,10);
if(hz==50) {
cic_d4(CIC_PAL);
} else {
cic_d4(CIC_NTSC);
}
printf("ok\n");
}
}
static void cmd_vmode(void) {
int32_t hz;
if(get_cic_state() != CIC_PAIR) {
printf("not in pair mode\n");
} else {
hz = parse_unsigned(50,60,10);
if(hz==50) {
cic_videomode(CIC_PAL);
} else {
cic_videomode(CIC_NTSC);
}
printf("ok\n");
}
}
void cmd_put(void) {
if(*curchar != 0) {
file_open((uint8_t*)curchar, FA_CREATE_ALWAYS | FA_WRITE);
if(file_res) {
printf("FAIL: error opening file %s\n", curchar);
} else {
printf("OK, start xmodem transfer now.\n");
xmodem_rxfile(&file_handle);
}
file_close();
} else {
printf("Usage: put <filename>\n");
}
}
void cmd_rm(void) {
FRESULT res = f_unlink(curchar);
if(res) printf("Error %d removing %s\n", res, curchar);
}
void cmd_mapper(void) {
int32_t mapper;
mapper = parse_unsigned(0,7,10);
set_mapper((uint8_t)mapper & 0x7);
printf("mapper set to %ld\n", mapper);
}
void cmd_sreset(void) {
if(*curchar != 0) {
int32_t resetstate;
resetstate = parse_unsigned(0,1,10);
snes_reset(resetstate);
} else {
snes_reset(1);
delay_ms(20);
snes_reset(0);
}
}
void cmd_settime(void) {
struct tm time;
if(strlen(curchar) != 4+2+2 + 2+2+2) {
printf("invalid time format (need YYYYMMDDhhmmss)\n");
} else {
time.tm_sec = atoi(curchar+4+2+2+2+2);
curchar[4+2+2+2+2] = 0;
time.tm_min = atoi(curchar+4+2+2+2);
curchar[4+2+2+2] = 0;
time.tm_hour = atoi(curchar+4+2+2);
curchar[4+2+2] = 0;
time.tm_mday = atoi(curchar+4+2);
curchar[4+2] = 0;
time.tm_mon = atoi(curchar+4);
curchar[4] = 0;
time.tm_year = atoi(curchar);
set_rtc(&time);
}
}
void cmd_time(void) {
struct tm time;
read_rtc(&time);
printf("%04d-%02d-%02d %02d:%02d:%02d\n", time.tm_year, time.tm_mon,
time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec);
}
void cmd_setfeature(void) {
uint8_t feat = parse_unsigned(0, 255, 16);
fpga_set_features(feat);
}
void cmd_hexdump(void) {
uint32_t offset = parse_unsigned(0, 16777215, 16);
uint32_t len = parse_unsigned(0, 16777216, 16);
sram_hexdump(offset, len);
}
void cmd_w8(void) {
uint32_t offset = parse_unsigned(0, 16777215, 16);
uint8_t val = parse_unsigned(0, 255, 16);
sram_writebyte(val, offset);
}
void cmd_w16(void) {
uint32_t offset = parse_unsigned(0, 16777215, 16);
uint16_t val = parse_unsigned(0, 65535, 16);
sram_writeshort(val, offset);
}
void cmd_memsel(void) {
uint8_t unit = parse_unsigned(0,1,10);
fpga_select_mem(unit);
}
/* ------------------------------------------------------------------------- */
/* CLI interface functions */
/* ------------------------------------------------------------------------- */
void cli_init(void) {
}
void cli_entrycheck() {
if(uart_gotc() && uart_getc() == 27) {
printf("*** BREAK\n");
cli_loop();
}
}
void cli_loop(void) {
snes_reset(1);
while (1) {
curchar = getline(">");
printf("\n");
/* Process medium changes before executing the command */
if (disk_state != DISK_OK && disk_state != DISK_REMOVED) {
FRESULT res;
printf("Medium changed... ");
res = f_mount(0,&fatfs);
if (res != FR_OK) {
printf("Failed to mount new medium, result %d\n",res);
} else {
printf("Ok\n");
}
}
/* Remove whitespace */
while (*curchar == ' ') curchar++;
while (strlen(curchar) > 0 && curchar[strlen(curchar)-1] == ' ')
curchar[strlen(curchar)-1] = 0;
/* Ignore empty lines */
if (strlen(curchar) == 0)
continue;
/* Parse command */
int8_t command = parse_wordlist(command_words);
if (command < 0)
continue;
FRESULT res;
switch (command) {
case CMD_CD:
#if _FS_RPATH
if (strlen(curchar) == 0) {
f_getcwd((TCHAR*)file_lfn, 255);
printf("%s\n",file_lfn);
break;
}
res = f_chdir((const TCHAR *)curchar);
if (res != FR_OK) {
printf("chdir %s failed with result %d\n",curchar,res);
} else {
printf("Ok.\n");
}
#else
printf("cd not supported.\n");
res;
#endif
break;
case CMD_RESET:
cmd_reset();
break;
case CMD_SRESET:
cmd_sreset();
break;
case CMD_DIR:
case CMD_LS:
cmd_show_directory();
break;
case CMD_RESUME:
return;
break;
case CMD_LOADROM:
cmd_loadrom();
break;
case CMD_LOADRAW:
cmd_loadraw();
break;
case CMD_SAVERAW:
cmd_saveraw();
break;
case CMD_RM:
cmd_rm();
break;
case CMD_D4:
cmd_d4();
break;
case CMD_VMODE:
cmd_vmode();
break;
case CMD_PUT:
cmd_put();
break;
case CMD_MAPPER:
cmd_mapper();
break;
case CMD_SETTIME:
cmd_settime();
break;
case CMD_TIME:
cmd_time();
break;
case CMD_TEST:
testbattery();
break;
case CMD_SETFEATURE:
cmd_setfeature();
break;
case CMD_HEXDUMP:
cmd_hexdump();
break;
case CMD_W8:
cmd_w8();
break;
case CMD_W16:
cmd_w16();
break;
case CMD_MEMSEL:
cmd_memsel();
break;
}
}
}

34
src/tests/cli.h Normal file
View File

@@ -0,0 +1,34 @@
/* tapplay - TAP file playback for sd2iec hardware
Copyright (C) 2009 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
cli.h: Definitions for cli.c
*/
#ifndef CLI_H
#define CLI_H
void cli_init(void);
void cli_loop(void);
void cli_entrycheck(void);
#endif

109
src/tests/clock.c Normal file
View File

@@ -0,0 +1,109 @@
/* ___DISCLAIMER___ */
/* clock.c: PLL, CCLK, PCLK controls */
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "clock.h"
#include "bits.h"
#include "uart.h"
void clock_disconnect() {
disconnectPLL0();
disablePLL0();
}
void clock_init() {
/* set flash access time to 5 clks (80<f<=100MHz) */
setFlashAccessTime(5);
/* setup PLL0 for ~44100*256*8 Hz
Base clock: 12MHz
Multiplier: 429
Pre-Divisor: 19
Divisor: 6
(want: 90316800, get: 90315789.47)
-> DAC freq = 44099.5 Hz
-> FPGA freq = 11289473.7Hz
First, disable and disconnect PLL0.
*/
// clock_disconnect();
/* PLL is disabled and disconnected. setup PCLK NOW as it cannot be changed
reliably with PLL0 connected.
see:
http://ics.nxp.com/support/documents/microcontrollers/pdf/errata.lpc1754.pdf
*/
/* continue with PLL0 setup:
enable the xtal oscillator and wait for it to become stable
set the oscillator as clk source for PLL0
set PLL0 multiplier+predivider
enable PLL0
set CCLK divider
wait for PLL0 to lock
connect PLL0
done
*/
enableMainOsc();
setClkSrc(CLKSRC_MAINOSC);
// XXX setPLL0MultPrediv(429, 19);
// XXX setPLL0MultPrediv(23, 2);
setPLL0MultPrediv(12, 1);
enablePLL0();
setCCLKDiv(3);
connectPLL0();
}
void setFlashAccessTime(uint8_t clocks) {
LPC_SC->FLASHCFG=FLASHTIM(clocks);
}
void setPLL0MultPrediv(uint16_t mult, uint8_t prediv) {
LPC_SC->PLL0CFG=PLL_MULT(mult) | PLL_PREDIV(prediv);
PLL0feed();
}
void enablePLL0() {
LPC_SC->PLL0CON |= PLLE0;
PLL0feed();
}
void disablePLL0() {
LPC_SC->PLL0CON &= ~PLLE0;
PLL0feed();
}
void connectPLL0() {
while(!(LPC_SC->PLL0STAT&PLOCK0));
LPC_SC->PLL0CON |= PLLC0;
PLL0feed();
}
void disconnectPLL0() {
LPC_SC->PLL0CON &= ~PLLC0;
PLL0feed();
}
void setCCLKDiv(uint8_t div) {
LPC_SC->CCLKCFG=CCLK_DIV(div);
}
void enableMainOsc() {
LPC_SC->SCS=OSCEN;
while(!(LPC_SC->SCS&OSCSTAT));
}
void disableMainOsc() {
LPC_SC->SCS=0;
}
void PLL0feed() {
LPC_SC->PLL0FEED=0xaa;
LPC_SC->PLL0FEED=0x55;
}
void setClkSrc(uint8_t src) {
LPC_SC->CLKSRCSEL=src;
}

79
src/tests/clock.h Normal file
View File

@@ -0,0 +1,79 @@
#ifndef _CLOCK_H
#define _CLOCK_H
#define PLL_MULT(x) ((x-1)&0x7fff)
#define PLL_PREDIV(x) (((x-1)<<16)&0xff0000)
#define CCLK_DIV(x) ((x-1)&0xff)
#define CLKSRC_MAINOSC (1)
#define PLLE0 (1<<0)
#define PLLC0 (1<<1)
#define PLOCK0 (1<<26)
#define OSCEN (1<<5)
#define OSCSTAT (1<<6)
#define FLASHTIM(x) (((x-1)<<12)|0x3A)
#define PCLK_CCLK(x) (1<<(x))
#define PCLK_CCLK4(x) (0)
#define PCLK_CCLK8(x) (3<<(x))
#define PCLK_CCLK2(x) (2<<(x))
/* shift values for use with PCLKSEL0 */
#define PCLK_WDT (0)
#define PCLK_TIMER0 (2)
#define PCLK_TIMER1 (4)
#define PCLK_UART0 (6)
#define PCLK_UART1 (8)
#define PCLK_PWM1 (12)
#define PCLK_I2C0 (14)
#define PCLK_SPI (16)
#define PCLK_SSP1 (20)
#define PCLK_DAC (22)
#define PCLK_ADC (24)
#define PCLK_CAN1 (26)
#define PCLK_CAN2 (28)
#define PCLK_ACF (30)
/* shift values for use with PCLKSEL1 */
#define PCLK_QEI (0)
#define PCLK_GPIOINT (2)
#define PCLK_PCB (4)
#define PCLK_I2C1 (6)
#define PCLK_SSP0 (10)
#define PCLK_TIMER2 (12)
#define PCLK_TIMER3 (14)
#define PCLK_UART2 (16)
#define PCLK_UART3 (18)
#define PCLK_I2C2 (20)
#define PCLK_I2S (22)
#define PCLK_RIT (26)
#define PCLK_SYSCON (28)
#define PCLK_MC (30)
void clock_disconnect(void);
void clock_init(void);
void setFlashAccessTime(uint8_t clocks);
void setPLL0MultPrediv(uint16_t mult, uint8_t prediv);
void enablePLL0(void);
void disablePLL0(void);
void connectPLL0(void);
void disconnectPLL0(void);
void setCCLKDiv(uint8_t div);
void enableMainOsc(void);
void disableMainOsc(void);
void PLL0feed(void);
void setClkSrc(uint8_t src);
#endif

29
src/tests/conf2h.awk Normal file
View File

@@ -0,0 +1,29 @@
#! /usr/bin/gawk -f
# Trivial little script to convert from a makefile-style configuration
# file to a C header. No copyright claimed.
BEGIN {
print "// autoconf.h generated from " ARGV[1] " at " strftime() "\n" \
"#ifndef AUTOCONF_H\n" \
"#define AUTOCONF_H"
}
/^#/ { sub(/^#/,"//") }
/^CONFIG_.*=/ {
if (/=n$/) {
sub(/^/,"// ");
} else {
sub(/^/,"#define ")
if (/=y$/) {
sub(/=.*$/,"")
} else {
sub(/=/," ")
}
}
}
{ print }
END { print "#endif" }

4
src/tests/config Normal file
View File

@@ -0,0 +1,4 @@
CONFIG_VERSION=0.0.1
CONFIG_FWVER=16777214
#CONFIG_FWVER=1146310227
CONFIG_MCU_FOSC=12000000

97
src/tests/config.h Normal file
View File

@@ -0,0 +1,97 @@
#ifndef _CONFIG_H
#define _CONFIG_H
// #define DEBUG_FS
// #define DEBUG_SD
// #define DEBUG_IRQ
// #define DEBUG_MSU1
#define VER "0.0.1(NSFW)"
#define IN_AHBRAM __attribute__ ((section(".ahbram")))
#define SD_DT_INT_SETUP() do {\
BITBAND(LPC_GPIOINT->IO2IntEnR, SD_DT_BIT) = 1;\
BITBAND(LPC_GPIOINT->IO2IntEnF, SD_DT_BIT) = 1;\
} while(0)
#define SD_CHANGE_DETECT (BITBAND(LPC_GPIOINT->IO2IntStatR, SD_DT_BIT)\
|BITBAND(LPC_GPIOINT->IO2IntStatF, SD_DT_BIT))
#define SD_CHANGE_CLR() do {LPC_GPIOINT->IO2IntClr = BV(SD_DT_BIT);} while(0)
#define SD_DT_REG LPC_GPIO0
#define SD_DT_BIT 8
#define SD_WP_REG LPC_GPIO0
#define SD_WP_BIT 6
#define SDCARD_DETECT (!(BITBAND(SD_DT_REG->FIOPIN, SD_DT_BIT)))
#define SDCARD_WP (BITBAND(SD_WP_REG->FIOPIN, SD_WP_BIT))
#define SD_SUPPLY_VOLTAGE (1L<<21) /* 3.3V - 3.4V */
#define CONFIG_SD_BLOCKTRANSFER 1
#define CONFIG_SD_AUTO_RETRIES 10
// #define SD_CHANGE_VECT
// #define CONFIG_SD_DATACRC 1
#define CONFIG_UART_NUM 3
// #define CONFIG_CPU_FREQUENCY 90315789
#define CONFIG_CPU_FREQUENCY 96000000
//#define CONFIG_CPU_FREQUENCY 46000000
#define CONFIG_UART_PCLKDIV 1
#define CONFIG_UART_TX_BUF_SHIFT 8
#define CONFIG_UART_BAUDRATE 921600
#define CONFIG_UART_DEADLOCKABLE
#define SSP_CLK_DIVISOR_FAST 2
#define SSP_CLK_DIVISOR_SLOW 250
#define SSP_CLK_DIVISOR_FPGA_FAST 6
#define SSP_CLK_DIVISOR_FPGA_SLOW 20
#define SNES_RESET_REG LPC_GPIO1
#define SNES_RESET_BIT 26
#define SNES_CIC_D0_REG LPC_GPIO0
#define SNES_CIC_D0_BIT 1
#define SNES_CIC_D1_REG LPC_GPIO0
#define SNES_CIC_D1_BIT 0
#define SNES_CIC_STATUS_REG LPC_GPIO1
#define SNES_CIC_STATUS_BIT 29
#define SNES_CIC_PAIR_REG LPC_GPIO1
#define SNES_CIC_PAIR_BIT 25
#define FPGA_MCU_RDY_REG LPC_GPIO2
#define FPGA_MCU_RDY_BIT 9
#define QSORT_MAXELEM 2048
#define SSP_REGS LPC_SSP0
#define SSP_PCLKREG PCLKSEL1
// 1: PCLKSEL0
#define SSP_PCLKBIT 10
// 1: 20
#define SSP_DMAID_TX 0
// 1: 2
#define SSP_DMAID_RX 1
// 1: 3
#define SSP_DMACH LPC_GPDMACH0
#define SD_CLKREG LPC_GPIO0
#define SD_CMDREG LPC_GPIO0
#define SD_DAT0REG LPC_GPIO2
#define SD_DAT1REG LPC_GPIO2
#define SD_DAT2REG LPC_GPIO2
#define SD_DAT3REG LPC_GPIO2
#define SD_CLKPIN (7)
#define SD_CMDPIN (9)
#define SD_DAT0PIN (0)
#define SD_DAT1PIN (1)
#define SD_DAT2PIN (2)
#define SD_DAT3PIN (3)
#define SD_DAT (LPC_GPIO2->FIOPIN0)
#endif

92
src/tests/crc.S Normal file
View File

@@ -0,0 +1,92 @@
/* CRC-7/CRC-16 (XModem) implementation for Cortex M3
*
* Written 2010 by Ingo Korb
*/
.syntax unified
.section .text
/* uint8_t crc7update(uint8_t crc, const uint8_t data) */
.global crc7update
.thumb_func
crc7update:
mov r2, #8 // number of bits to process
lsl r1, r1, #24 // pre-shift data byte to top of word
loop:
lsl r0, r0, #1 // shift CRC
lsls r1, r1, #1 // shift data byte (highest bit now in C)
bcc 0f // jump if bit was 0
eor r0, r0, #0x80 // invert top bit of CRC if not
0: tst r0, #0x80 // test top bit of CRC
beq 1f // skip if top bit is clear
eor r0, r0, #0x09 // apply polinomial
1: subs r2, r2, #1 // decrememt bit cointer
bne loop // loop for next bit
uxtb r0, r0 // clear top bits of result
bx lr // return
/* uint16_t crc_xmodem_block(uint16_t crc, uint8_t *data, uint32_t len) */
.global crc_xmodem_block
.thumb_func
crc_xmodem_block:
adr r12, crc_table // load address of crc table
blockloop:
ldrb.w r3, [r1], #1 // read data byte
eor r3, r3, r0, lsr #8 // EOR data byte
ldrh r3, [r12, r3, lsl #1] // load value from CRC table
eor r0, r3, r0, lsl #8 // update CRC
uxth r0, r0 // clear top bits of result
subs r2, r2, #1 // decrement length
bne blockloop // loop while length > 0
bx lr // return
/* uint16_t crc_xmodem_block(uint16_t crc, uint8_t *data, uint32_t len) */
.global crc_xmodem_update
.thumb_func
crc_xmodem_update:
adr r2, crc_table // load address of crc table
eor r1, r1, r0, lsr #8 // EOR data byte
ldrh r3, [r2, r1, lsl #1] // load value from CRC table
eor r0, r3, r0, lsl #8 // update CRC
uxth r0, r0 // clear top bits of result
bx lr // return
crc_table:
.short 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7
.short 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef
.short 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6
.short 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de
.short 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485
.short 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d
.short 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4
.short 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc
.short 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823
.short 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b
.short 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12
.short 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a
.short 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41
.short 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49
.short 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70
.short 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78
.short 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f
.short 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067
.short 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e
.short 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256
.short 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d
.short 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405
.short 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c
.short 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634
.short 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab
.short 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3
.short 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a
.short 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92
.short 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9
.short 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1
.short 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8
.short 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
.end

11
src/tests/crc.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef CRC_H
#define CRC_H
uint8_t crc7update(uint8_t crc, uint8_t data);
uint16_t crc_xmodem_update(uint16_t crc, uint8_t data);
uint16_t crc_xmodem_block(uint16_t crc, const uint8_t *data, uint32_t length);
// AVR-libc compatibility
#define _crc_xmodem_update(crc,data) crc_xmodem_update(crc,data)
#endif

110
src/tests/crc32.c Normal file
View File

@@ -0,0 +1,110 @@
/**
* \file crc32.c
* Functions and types for CRC checks.
*
* Generated on Sat Sep 25 18:06:34 2010,
* by pycrc v0.7.1, http://www.tty1.net/pycrc/
* using the configuration:
* Width = 32
* Poly = 0x04c11db7
* XorIn = 0xffffffff
* ReflectIn = True
* XorOut = 0xffffffff
* ReflectOut = True
* Algorithm = table-driven
* Direct = True
*****************************************************************************/
#include "crc32.h"
#include "config.h"
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include <stdlib.h>
/**
* Static table used for the table_driven implementation.
*****************************************************************************/
static const uint32_t crc32_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
/**
* Update the crc value with new data.
*
* \param crc The current crc value.
* \param data Pointer to a buffer of \a data_len bytes.
* \param data_len Number of bytes in the \a data buffer.
* \return The updated crc value.
*****************************************************************************/
uint32_t crc32_update(uint32_t crc, const unsigned char data)
{
unsigned int tbl_idx;
tbl_idx = (crc ^ data) & 0xff;
crc = (crc32_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff;
return crc & 0xffffffff;
}

68
src/tests/crc32.h Normal file
View File

@@ -0,0 +1,68 @@
/**
* \file crc32.h
* Functions and types for CRC checks.
*
* Generated on Sat Sep 25 18:06:37 2010,
* by pycrc v0.7.1, http://www.tty1.net/pycrc/
* using the configuration:
* Width = 32
* Poly = 0x04c11db7
* XorIn = 0xffffffff
* ReflectIn = True
* XorOut = 0xffffffff
* ReflectOut = True
* Algorithm = table-driven
* Direct = True
*****************************************************************************/
#ifndef __CRC___H__
#define __CRC___H__
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* The definition of the used algorithm.
*****************************************************************************/
#define CRC_ALGO_TABLE_DRIVEN 1
/**
* Calculate the initial crc value.
*
* \return The initial crc value.
*****************************************************************************/
static inline uint32_t crc_init(void)
{
return 0xffffffff;
}
/**
* Update the crc value with new data.
*
* \param crc The current crc value.
* \param data Pointer to a buffer of \a data_len bytes.
* \param data_len Number of bytes in the \a data buffer.
* \return The updated crc value.
*****************************************************************************/
uint32_t crc32_update(uint32_t crc, const unsigned char data);
/**
* Calculate the final crc value.
*
* \param crc The current crc value.
* \return The final crc value.
*****************************************************************************/
static inline uint32_t crc32_finalize(uint32_t crc)
{
return crc ^ 0xffffffff;
}
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif
#endif /* __CRC___H__ */

118
src/tests/diskio.h Normal file
View File

@@ -0,0 +1,118 @@
/*-----------------------------------------------------------------------
/ Low level disk interface modlue include file (C)ChaN, 2010
/-----------------------------------------------------------------------*/
#ifndef _DISKIO
#define _READONLY 0 /* 1: Remove write functions */
#define _USE_IOCTL 1 /* 1: Use disk_ioctl fucntion */
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "integer.h"
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/**
* struct diskinfo0_t - disk info data structure for page 0
* @validbytes : Number of valid bytes in this struct
* @maxpage : Highest diskinfo page supported
* @disktype : type of the disk (DISK_TYPE_* values)
* @sectorsize : sector size divided by 256
* @sectorcount: number of sectors on the disk
*
* This is the struct returned in the data buffer when disk_getinfo
* is called with page=0.
*/
typedef struct {
uint8_t validbytes;
uint8_t maxpage;
uint8_t disktype;
uint8_t sectorsize; /* divided by 256 */
uint32_t sectorcount; /* 2 TB should be enough... (512 byte sectors) */
} diskinfo0_t;
/*---------------------------------------*/
/* Prototypes for disk control functions */
int assign_drives (int, int);
DSTATUS disk_initialize (BYTE);
DSTATUS disk_status (BYTE);
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
#if _READONLY == 0
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
#endif
#define disk_ioctl(a,b,c) RES_OK
void disk_init(void);
/* Will be set to DISK_ERROR if any access on the card fails */
enum diskstates { DISK_CHANGED = 0, DISK_REMOVED, DISK_OK, DISK_ERROR };
extern int sd_offload, ff_sd_offload, sd_offload_tgt, newcard;
extern int sd_offload_partial;
extern uint16_t sd_offload_partial_start;
extern uint16_t sd_offload_partial_end;
extern volatile enum diskstates disk_state;
/* Disk type - part of the external API except for ATA2! */
#define DISK_TYPE_ATA 0
#define DISK_TYPE_ATA2 1
#define DISK_TYPE_SD 2
#define DISK_TYPE_DF 3
#define DISK_TYPE_NONE 7
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (defined for FatFs) */
#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */
#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */
#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */
#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */
/* Generic command */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
/* NAND specific ioctl command */
#define NAND_FORMAT 30 /* Create physical format */
#define _DISKIO
#endif

20
src/tests/faulthandler.c Normal file
View File

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

3805
src/tests/ff.c Normal file

File diff suppressed because it is too large Load Diff

547
src/tests/ff.h Normal file
View File

@@ -0,0 +1,547 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module include file R0.08a (C)ChaN, 2010
/----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following trems.
/
/ Copyright (C) 2010, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/----------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 8255 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if _FATFS != _FFCONF
#error Wrong configuration file (ffconf.h).
#endif
/* DBCS code ranges and SBCS extend char conversion table */
#if _CODE_PAGE == 932 /* Japanese Shift-JIS */
#define _DF1S 0x81 /* DBC 1st byte range 1 start */
#define _DF1E 0x9F /* DBC 1st byte range 1 end */
#define _DF2S 0xE0 /* DBC 1st byte range 2 start */
#define _DF2E 0xFC /* DBC 1st byte range 2 end */
#define _DS1S 0x40 /* DBC 2nd byte range 1 start */
#define _DS1E 0x7E /* DBC 2nd byte range 1 end */
#define _DS2S 0x80 /* DBC 2nd byte range 2 start */
#define _DS2E 0xFC /* DBC 2nd byte range 2 end */
#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
#define _DF1S 0x81
#define _DF1E 0xFE
#define _DS1S 0x40
#define _DS1E 0x7E
#define _DS2S 0x80
#define _DS2E 0xFE
#elif _CODE_PAGE == 949 /* Korean */
#define _DF1S 0x81
#define _DF1E 0xFE
#define _DS1S 0x41
#define _DS1E 0x5A
#define _DS2S 0x61
#define _DS2E 0x7A
#define _DS3S 0x81
#define _DS3E 0xFE
#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
#define _DF1S 0x81
#define _DF1E 0xFE
#define _DS1S 0x40
#define _DS1E 0x7E
#define _DS2S 0xA1
#define _DS2E 0xFE
#elif _CODE_PAGE == 437 /* U.S. (OEM) */
#define _DF1S 0
#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
#elif _CODE_PAGE == 720 /* Arabic (OEM) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
#elif _CODE_PAGE == 737 /* Greek (OEM) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \
0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
#elif _CODE_PAGE == 775 /* Baltic (OEM) */
#define _DF1S 0
#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */
#define _DF1S 0
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */
#define _DF1S 0
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \
0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF}
#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */
#define _DF1S 0
#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \
0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \
0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF}
#elif _CODE_PAGE == 857 /* Turkish (OEM) */
#define _DF1S 0
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \
0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */
#define _DF1S 0
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
#elif _CODE_PAGE == 862 /* Hebrew (OEM) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
#elif _CODE_PAGE == 866 /* Russian (OEM) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF}
#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \
0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
#elif _CODE_PAGE == 1253 /* Greek (Windows) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \
0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF}
#elif _CODE_PAGE == 1254 /* Turkish (Windows) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \
0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
#elif _CODE_PAGE == 1256 /* Arabic (Windows) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF}
#elif _CODE_PAGE == 1257 /* Baltic (Windows) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */
#define _DF1S 0
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \
0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F}
#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */
#define _DF1S 0
#else
#error Unknown code page
#endif
/* Definitions of volume management */
#if _MULTI_PARTITION /* Multiple partition configuration */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */
typedef struct {
BYTE pd; /* Physical drive# */
BYTE pt; /* Partition # (0-3) */
} PARTITION;
extern const PARTITION VolToPart[]; /* Volume - Physical location resolution table */
#else /* Single partition configuration */
#define LD2PD(vol) (vol) /* Logical drive# is bound to the same physical drive# */
#define LD2PT(vol) 0 /* Always mounts the 1st partition */
#endif
/* Type of path name strings on FatFs API */
#if _LFN_UNICODE /* Unicode string */
#if !_USE_LFN
#error _LFN_UNICODE must be 0 in non-LFN cfg.
#endif
#ifndef _INC_TCHAR
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#endif
#else /* ANSI/OEM string */
#ifndef _INC_TCHAR
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* File system object structure (FATFS) */
typedef struct {
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
BYTE drv; /* Physical drive number */
BYTE csize; /* Sectors per cluster (1,2,4...128) */
BYTE n_fats; /* Number of FAT copies (1,2) */
BYTE wflag; /* win[] dirty flag (1:must be written back) */
BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
#if _MAX_SS != 512
WORD ssize; /* Bytes per sector (512,1024,2048,4096) */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !_FS_READONLY
DWORD last_clust; /* Last allocated cluster */
DWORD free_clust; /* Number of free clusters */
DWORD fsi_sector; /* fsinfo sector (FAT32) */
#endif
#if _FS_RPATH
DWORD cdir; /* Current directory start cluster (0:root) */
#endif
DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */
DWORD fsize; /* Sectors per FAT */
DWORD fatbase; /* FAT start sector */
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
DWORD database; /* Data start sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */
} FATFS;
/* File object structure (FIL) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
BYTE flag; /* File status flags */
BYTE pad1;
DWORD fptr; /* File read/write pointer (0 on file open) */
DWORD fsize; /* File size */
DWORD org_clust; /* File start cluster (0 when fsize==0) */
DWORD curr_clust; /* Current cluster */
DWORD dsect; /* Current data sector */
#if !_FS_READONLY
DWORD dir_sect; /* Sector containing the directory entry */
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
#endif
#if _USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */
#endif
#if _FS_SHARE
UINT lockid; /* File lock ID (index of file semaphore table) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File data read/write buffer */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
WORD index; /* Current read/write index number */
DWORD sclust; /* Table start cluster (0:Root dir) */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
#if _USE_LFN
WCHAR* lfn; /* Pointer to the LFN working buffer */
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
#endif
} DIR;
/* File status structure (FILINFO) */
typedef struct {
DWORD fsize; /* File size */
WORD fdate; /* Last modified date */
WORD ftime; /* Last modified time */
BYTE fattrib; /* Attribute */
TCHAR fname[13]; /* Short file name (8.3 format) */
DWORD clust; /* start cluster */
#if _USE_LFN
TCHAR* lfname; /* Pointer to the LFN buffer */
UINT lfsize; /* Size of LFN buffer in TCHAR */
#endif
} FILINFO;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */
FR_EXIST, /* (8) Acces denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume on the physical drive */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES /* (18) Number of open files > _FS_SHARE */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
/* Low Level functions */
FRESULT l_openfilebycluster(FATFS *fs, FIL *fp, const TCHAR *path, DWORD clust, DWORD fsize); /* Open a file by its start cluster using supplied file size */
FRESULT l_opendirbycluster (FATFS *fs, DIR *dj, const TCHAR *path, DWORD clust);
/* application level functions */
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */
FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */
FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
FRESULT f_close (FIL*); /* Close an open file object */
FRESULT f_opendir (DIR*, const TCHAR*); /* Open an existing directory */
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
FRESULT f_stat (const TCHAR*, FILINFO*); /* Get file status */
#if !_FS_READONLY
FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */
FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */
FRESULT f_truncate (FIL*); /* Truncate file */
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */
FRESULT f_mkdir (const TCHAR*); /* Create a new directory */
FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */
FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change timestamp of the file/dir */
FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */
#endif
#if _USE_FORWARD
FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */
#endif
#if _USE_MKFS
FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */
#endif
#if _FS_RPATH
FRESULT f_chdrive (BYTE); /* Change current drive */
FRESULT f_chdir (const TCHAR*); /* Change current directory */
FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */
#endif
#if _USE_STRFUNC
int f_putc (TCHAR, FIL*); /* Put a character to the file */
int f_puts (const TCHAR*, FIL*); /* Put a string to the file */
int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */
#ifndef EOF
#define EOF (-1)
#endif
#endif
#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->fsize)
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !_FS_READONLY
DWORD get_fattime (void);
#endif
/* Unicode support functions */
#if _USE_LFN /* Unicode - OEM code conversion */
WCHAR ff_convert (WCHAR, UINT); /* OEM-Unicode bidirectional conversion */
WCHAR ff_wtoupper (WCHAR); /* Unicode upper-case conversion */
#if _USE_LFN == 3 /* Memory functions */
void* ff_memalloc (UINT); /* Allocate memory block */
void ff_memfree (void*); /* Free memory block */
#endif
#endif
/* Sync functions */
#if _FS_REENTRANT
int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */
int ff_del_syncobj (_SYNC_t); /* Delete a sync object */
int ff_req_grant (_SYNC_t); /* Lock sync object */
void ff_rel_grant (_SYNC_t); /* Unlock sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access control and file status flags (FIL.flag) */
#define FA_READ 0x01
#define FA_OPEN_EXISTING 0x00
#define FA__ERROR 0x80
#if !_FS_READONLY
#define FA_WRITE 0x02
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA__WRITTEN 0x20
#define FA__DIRTY 0x40
#endif
/* FAT sub type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
/* File attribute bits for directory entry */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_VOL 0x08 /* Volume label */
#define AM_LFN 0x0F /* LFN entry */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#define AM_MASK 0x3F /* Mask of defined bits */
/* Fast seek function */
#define CREATE_LINKMAP 0xFFFFFFFF
/*--------------------------------*/
/* Multi-byte word access macros */
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
#else /* Use byte-by-byte access to the FAT structure */
#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _FATFS */

188
src/tests/ffconf.h Normal file
View File

@@ -0,0 +1,188 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file R0.08a (C)ChaN, 2010
/----------------------------------------------------------------------------/
/
/ CAUTION! Do not forget to make clean the project after any changes to
/ the configuration options.
/
/----------------------------------------------------------------------------*/
#ifndef _FFCONF
#define _FFCONF 8255 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function and Buffer Configurations
/----------------------------------------------------------------------------*/
#define _FS_TINY 0 /* 0:Normal or 1:Tiny */
/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
/ object instead of the sector buffer in the individual file object for file
/ data transfer. This reduces memory consumption 512 bytes each file object. */
#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
/ f_truncate and useless f_getfree. */
#define _FS_MINIMIZE 0 /* 0 to 3 */
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
/
/ 0: Full function.
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
/ are removed.
/ 2: f_opendir and f_readdir are removed in addition to 1.
/ 3: f_lseek is removed in addition to 2. */
#define _USE_STRFUNC 0 /* 0:Disable or 1/2:Enable */
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
#define _USE_MKFS 0 /* 0:Disable or 1:Enable */
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
#define _USE_FASTSEEK 1 /* 0:Disable or 1:Enable */
/* To enable fast seek feature, set _USE_FASTSEEK to 1. */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/----------------------------------------------------------------------------*/
#define _CODE_PAGE 1252
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows)
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
/ 949 - Korean (DBCS, OEM, Windows)
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
/ 1250 - Central Europe (Windows)
/ 1251 - Cyrillic (Windows)
/ 1252 - Latin 1 (Windows)
/ 1253 - Greek (Windows)
/ 1254 - Turkish (Windows)
/ 1255 - Hebrew (Windows)
/ 1256 - Arabic (Windows)
/ 1257 - Baltic (Windows)
/ 1258 - Vietnam (OEM, Windows)
/ 437 - U.S. (OEM)
/ 720 - Arabic (OEM)
/ 737 - Greek (OEM)
/ 775 - Baltic (OEM)
/ 850 - Multilingual Latin 1 (OEM)
/ 858 - Multilingual Latin 1 + Euro (OEM)
/ 852 - Latin 2 (OEM)
/ 855 - Cyrillic (OEM)
/ 866 - Russian (OEM)
/ 857 - Turkish (OEM)
/ 862 - Hebrew (OEM)
/ 874 - Thai (OEM, Windows)
/ 1 - ASCII only (Valid for non LFN cfg.)
*/
#define _USE_LFN 1 /* 0 to 3 */
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
/* The _USE_LFN option switches the LFN support.
/
/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN,
/ Unicode handling functions ff_convert() and ff_wtoupper() must be added
/ to the project. When enable to use heap, memory control functions
/ ff_memalloc() and ff_memfree() must be added to the project. */
#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
/* To switch the character code set on FatFs API to Unicode,
/ enable LFN feature and set _LFN_UNICODE to 1. */
#define _FS_RPATH 2 /* 0 to 2 */
/* The _FS_RPATH option configures relative path feature.
/
/ 0: Disable relative path feature and remove related functions.
/ 1: Enable relative path. f_chdrive() and f_chdir() are available.
/ 2: f_getcwd() is available in addition to 1.
/
/ Note that output of the f_readdir fnction is affected by this option. */
/*---------------------------------------------------------------------------/
/ Physical Drive Configurations
/----------------------------------------------------------------------------*/
#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */
/* Maximum sector size to be handled.
/ Always set 512 for memory card and hard disk but a larger value may be
/ required for floppy disk (512/1024) and optical disk (512/2048).
/ When _MAX_SS is larger than 512, GET_SECTOR_SIZE command must be implememted
/ to the disk_ioctl function. */
#define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */
/* When set to 0, each volume is bound to the same physical drive number and
/ it can mount only first primaly partition. When it is set to 1, each volume
/ is tied to the partitions listed in VolToPart[]. */
#define _USE_ERASE 0 /* 0:Disable or 1:Enable */
/* To enable sector erase feature, set _USE_ERASE to 1. */
/*---------------------------------------------------------------------------/
/ System Configurations
/----------------------------------------------------------------------------*/
#define _WORD_ACCESS 0 /* 0 or 1 */
/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS
/ option defines which access method is used to the word data on the FAT volume.
/
/ 0: Byte-by-byte access.
/ 1: Word access. Do not choose this unless following condition is met.
/
/ When the byte order on the memory is big-endian or address miss-aligned word
/ access results incorrect behavior, the _WORD_ACCESS must be set to 0.
/ If it is not the case, the value can also be set to 1 to improve the
/ performance and code size. */
/* Include a header file here to define sync object types on the O/S */
/* #include <windows.h>, <ucos_ii.h.h>, <semphr.h> or ohters. */
#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */
#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */
#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */
/* The _FS_REENTRANT option switches the reentrancy of the FatFs module.
/
/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect.
/ 1: Enable reentrancy. Also user provided synchronization handlers,
/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj
/ function must be added to the project. */
#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */
/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value
defines how many files can be opened simultaneously. */
#endif /* _FFCONFIG */

117
src/tests/fileops.c Normal file
View File

@@ -0,0 +1,117 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
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
fileops.c: simple file access functions
*/
#include "config.h"
#include "uart.h"
#include "ff.h"
#include "fileops.h"
#include "diskio.h"
/*
WCHAR ff_convert(WCHAR w, UINT dir) {
return w;
}*/
int newcard;
void file_init() {
file_res=f_mount(0, &fatfs);
newcard = 0;
}
void file_reinit(void) {
disk_init();
file_init();
}
FRESULT dir_open_by_filinfo(DIR* dir, FILINFO* fno) {
return l_opendirbycluster(&fatfs, dir, (TCHAR*)"", fno->clust);
}
void file_open_by_filinfo(FILINFO* fno) {
file_res = l_openfilebycluster(&fatfs, &file_handle, (TCHAR*)"", fno->clust, fno->fsize);
}
void file_open(uint8_t* filename, BYTE flags) {
if (disk_state == DISK_CHANGED) {
file_reinit();
newcard = 1;
}
file_res = f_open(&file_handle, (TCHAR*)filename, flags);
file_block_off = sizeof(file_buf);
file_block_max = sizeof(file_buf);
file_status = file_res ? FILE_ERR : FILE_OK;
}
void file_close() {
file_res = f_close(&file_handle);
}
void file_seek(uint32_t offset) {
file_res = f_lseek(&file_handle, (DWORD)offset);
}
UINT file_read() {
UINT bytes_read;
file_res = f_read(&file_handle, file_buf, sizeof(file_buf), &bytes_read);
return bytes_read;
}
UINT file_write() {
UINT bytes_written;
file_res = f_write(&file_handle, file_buf, sizeof(file_buf), &bytes_written);
if(bytes_written < sizeof(file_buf)) {
printf("wrote less than expected - card full?\n");
}
return bytes_written;
}
UINT file_readblock(void* buf, uint32_t addr, uint16_t size) {
UINT bytes_read;
file_res = f_lseek(&file_handle, addr);
if(file_handle.fptr != addr) {
return 0;
}
file_res = f_read(&file_handle, buf, size, &bytes_read);
return bytes_read;
}
UINT file_writeblock(void* buf, uint32_t addr, uint16_t size) {
UINT bytes_written;
file_res = f_lseek(&file_handle, addr);
if(file_res) return 0;
file_res = f_write(&file_handle, buf, size, &bytes_written);
return bytes_written;
}
uint8_t file_getc() {
if(file_block_off == file_block_max) {
file_block_max = file_read();
if(file_block_max == 0) file_status = FILE_EOF;
file_block_off = 0;
}
return file_buf[file_block_off++];
}

54
src/tests/fileops.h Normal file
View File

@@ -0,0 +1,54 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
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
fileops.h: simple file access functions
*/
#ifndef FILEOPS_H
#define FILEOPS_H
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "ff.h"
enum filestates { FILE_OK=0, FILE_ERR, FILE_EOF };
BYTE file_buf[512];
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;
void file_init(void);
void file_open(uint8_t* filename, BYTE flags);
FRESULT dir_open_by_filinfo(DIR* dir, FILINFO* fno_param);
void file_open_by_filinfo(FILINFO* fno);
void file_close(void);
void file_seek(uint32_t offset);
UINT file_read(void);
UINT file_write(void);
UINT file_readblock(void* buf, uint32_t addr, uint16_t size);
UINT file_writeblock(void* buf, uint32_t addr, uint16_t size);
uint8_t file_getc(void);
#endif

315
src/tests/filetypes.c Normal file
View File

@@ -0,0 +1,315 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
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
filetypes.c: directory scanning and file type detection
*/
#include <string.h>
#include "config.h"
#include "uart.h"
#include "filetypes.h"
#include "ff.h"
#include "smc.h"
#include "fileops.h"
#include "crc32.h"
#include "memory.h"
#include "led.h"
#include "sort.h"
uint16_t scan_flat(const char* path) {
DIR dir;
FRESULT res;
FILINFO fno;
fno.lfname = NULL;
res = f_opendir(&dir, (TCHAR*)path);
uint16_t numentries = 0;
if (res == FR_OK) {
for (;;) {
res = f_readdir(&dir, &fno);
if(res != FR_OK || fno.fname[0] == 0)break;
numentries++;
}
}
return numentries;
}
uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_tgt) {
DIR dir;
FILINFO fno;
FRESULT res;
uint8_t len;
TCHAR* fn;
static unsigned char depth = 0;
static uint32_t crc;
static uint32_t db_tgt;
static uint32_t next_subdir_tgt;
static uint32_t parent_tgt;
static uint32_t dir_end = 0;
static uint8_t was_empty = 0;
uint32_t dir_tgt;
uint16_t numentries;
uint32_t dirsize;
uint8_t pass = 0;
char buf[7];
char *size_units[3] = {" ", "k", "M"};
uint32_t entry_fsize;
uint8_t entry_unit_idx;
dir_tgt = this_dir_tgt;
if(depth==0) {
crc = 0;
db_tgt = SRAM_DB_ADDR+0x10;
dir_tgt = SRAM_DIR_ADDR;
next_subdir_tgt = SRAM_DIR_ADDR;
this_dir_tgt = SRAM_DIR_ADDR;
parent_tgt = 0;
printf("root dir @%lx\n", dir_tgt);
}
fno.lfsize = 255;
fno.lfname = (TCHAR*)file_lfn;
numentries=0;
for(pass = 0; pass < 2; pass++) {
if(pass) {
dirsize = 4*(numentries);
next_subdir_tgt += dirsize + 4;
if(parent_tgt) next_subdir_tgt += 4;
if(next_subdir_tgt > dir_end) {
dir_end = next_subdir_tgt;
}
// printf("path=%s depth=%d ptr=%lx entries=%d parent=%lx next subdir @%lx\n", path, depth, db_tgt, numentries, parent_tgt, next_subdir_tgt);
if(mkdb) {
// printf("d=%d Saving %lx to Address %lx [end]\n", depth, 0L, next_subdir_tgt - 4);
sram_writelong(0L, next_subdir_tgt - 4);
}
}
if(fno_param) {
res = dir_open_by_filinfo(&dir, fno_param);
} else {
res = f_opendir(&dir, path);
}
if (res == FR_OK) {
if(pass && parent_tgt && mkdb) {
/* write backlink to parent dir
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)) {
printf("switch! old=%lx ", db_tgt);
db_tgt &= 0xffff0000;
db_tgt += 0x00010000;
printf("new=%lx\n", 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_writebyte(0, db_tgt+sizeof(next_subdir_tgt));
sram_writeblock("../\0", db_tgt+sizeof(next_subdir_tgt)+sizeof(len), 4);
sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x81<<24), dir_tgt);
db_tgt += sizeof(next_subdir_tgt)+sizeof(len)+4;
dir_tgt += 4;
}
len = strlen((char*)path);
for (;;) {
// toggle_read_led();
res = f_readdir(&dir, &fno);
if (res != FR_OK || fno.fname[0] == 0) {
if(pass) {
if(!numentries) was_empty=1;
}
break;
}
fn = *fno.lfname ? fno.lfname : fno.fname;
if ((*fn == '.') || !(memcmp(fn, SYS_DIR_NAME, sizeof(SYS_DIR_NAME)))) continue;
if (fno.fattrib & AM_DIR) {
depth++;
if(depth < FS_MAX_DEPTH) {
numentries++;
if(pass) {
path[len]='/';
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
if(mkdb) {
uint16_t pathlen = strlen(path);
// printf("d=%d Saving %lx to Address %lx [dir]\n", depth, db_tgt, dir_tgt);
/* save element:
- path name
- pointer to sub dir structure */
if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2))&0xffff)) {
printf("switch! old=%lx ", db_tgt);
db_tgt &= 0xffff0000;
db_tgt += 0x00010000;
printf("new=%lx\n", db_tgt);
}
// printf(" Saving dir descriptor to %lx tgt=%lx, path=%s\n", db_tgt, next_subdir_tgt, path);
/* write element pointer to current dir structure */
sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x80<<24), dir_tgt);
/* save element:
- path name
- pointer to sub dir structure */
sram_writelong((next_subdir_tgt-SRAM_MENU_ADDR), db_tgt);
sram_writebyte(len+1, db_tgt+sizeof(next_subdir_tgt));
sram_writeblock(path, db_tgt+sizeof(next_subdir_tgt)+sizeof(len), pathlen);
sram_writeblock("/\0", 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;
scan_dir(path, &fno, mkdb, next_subdir_tgt);
dir_tgt += 4;
was_empty = 0;
}
}
depth--;
path[len]=0;
} else {
SNES_FTYPE type = determine_filetype((char*)fn);
if(type != TYPE_UNKNOWN) {
numentries++;
if(pass) {
if(mkdb) {
/* snes_romprops_t romprops; */
path[len]='/';
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
uint16_t pathlen = strlen(path);
switch(type) {
case TYPE_IPS:
case TYPE_SMC:
/* file_open_by_filinfo(&fno);
if(file_res){
printf("ZOMG NOOOO %d\n", file_res);
}
smc_id(&romprops);
file_close(); */
/* 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);
if((db_tgt&0xffff) > ((0x10000-(sizeof(len) + pathlen + sizeof(buf)-1 + 1))&0xffff)) {
printf("switch! old=%lx ", db_tgt);
db_tgt &= 0xffff0000;
db_tgt += 0x00010000;
printf("new=%lx\n", db_tgt);
}
sram_writelong((db_tgt-SRAM_MENU_ADDR) | ((uint32_t)type << 24), dir_tgt);
dir_tgt += 4;
/* save element:
- index of last slash character
- file name
- file size */
/* sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); */
entry_fsize = fno.fsize;
entry_unit_idx = 0;
while(entry_fsize > 9999) {
entry_fsize >>= 10;
entry_unit_idx++;
}
snprintf(buf, sizeof(buf), "% 5ld", entry_fsize);
strncat(buf, size_units[entry_unit_idx], 1);
sram_writeblock(buf, db_tgt, sizeof(buf)-1);
sram_writebyte(len+1, db_tgt + sizeof(buf)-1);
sram_writeblock(path, db_tgt + sizeof(len) + sizeof(buf)-1, pathlen + 1);
// sram_writelong(fno.fsize, db_tgt + sizeof(len) + pathlen + 1);
db_tgt += sizeof(len) + pathlen + sizeof(buf)-1 + 1;
break;
case TYPE_UNKNOWN:
default:
break;
}
path[len]=0;
/* printf("%s ", path);
_delay_ms(30); */
}
} else {
TCHAR* fn2 = fn;
while(*fn2 != 0) {
crc += crc32_update(crc, *((unsigned char*)fn2++));
}
}
}
/* printf("%s/%s\n", path, fn);
_delay_ms(50); */
}
}
} else uart_putc(0x30+res);
}
// printf("db_tgt=%lx dir_end=%lx\n", db_tgt, dir_end);
sram_writelong(db_tgt, SRAM_DB_ADDR+4);
sram_writelong(dir_end, SRAM_DB_ADDR+8);
return crc;
}
SNES_FTYPE determine_filetype(char* filename) {
char* ext = strrchr(filename, '.');
if(ext == NULL)
return TYPE_UNKNOWN;
if( (!strcasecmp(ext+1, "SMC"))
||(!strcasecmp(ext+1, "SFC"))
||(!strcasecmp(ext+1, "FIG"))
||(!strcasecmp(ext+1, "BS"))
) {
return TYPE_SMC;
}
if( (!strcasecmp(ext+1, "IPS"))
||(!strcasecmp(ext+1, "UPS"))
) {
return TYPE_IPS;
}
/* later
if(!strcasecmp_P(ext+1, PSTR("SRM"))) {
return TYPE_SRM;
}
if(!strcasecmp_P(ext+1, PSTR("SPC"))) {
return TYPE_SPC;
}*/
return TYPE_UNKNOWN;
}
FRESULT get_db_id(uint32_t* id) {
file_open((uint8_t*)"/sd2snes/sd2snes.db", FA_READ);
if(file_res == FR_OK) {
file_readblock(id, 0, 4);
/* XXX */// *id=0xdead;
file_close();
} else {
*id=0xdeadbeef;
}
return file_res;
}
int get_num_dirent(uint32_t addr) {
int result = 0;
while(sram_readlong(addr+result*4)) {
result++;
}
return result;
}
void sort_all_dir(uint32_t endaddr) {
uint32_t entries = 0;
uint32_t current_base = SRAM_DIR_ADDR;
while(current_base<(endaddr)) {
while(sram_readlong(current_base+entries*4)) {
entries++;
}
printf("sorting dir @%lx, entries: %ld\n", current_base, entries);
sort_dir(current_base, entries);
current_base += 4*entries + 4;
entries = 0;
}
}

58
src/tests/filetypes.h Normal file
View File

@@ -0,0 +1,58 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
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
filetypes.h: directory scanning and file type detection
*/
#ifndef FILETYPES_H
#define FILETYPES_H
#ifdef DEBUG_FS
#define DBG_FS
#else
#define DBG_FS while(0)
#endif
#include "ff.h"
#define FS_MAX_DEPTH (10)
#define SYS_DIR_NAME ((const uint8_t*)"sd2snes")
typedef enum {
TYPE_UNKNOWN = 0, /* 0 */
TYPE_SMC, /* 1 */
TYPE_SRM, /* 2 */
TYPE_SPC, /* 3 */
TYPE_IPS /* 4 */
} SNES_FTYPE;
char fs_path[256];
SNES_FTYPE determine_filetype(char* filename);
//uint32_t scan_fs();
uint16_t scan_flat(const char* path);
uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_subdir_tgt);
FRESULT get_db_id(uint32_t*);
int get_num_dirent(uint32_t addr);
void sort_all_dir(uint32_t endaddr);
#endif

4
src/tests/flash.cfg Normal file
View File

@@ -0,0 +1,4 @@
# script running on reset
init
script flash.script

12
src/tests/flash.script Normal file
View File

@@ -0,0 +1,12 @@
# mthomas 4/2008, tested with OpenOCD SVN555
#flash probe 0
#flash erase_check 0
#flash protect_check 0
#flash info 0
reset init
flash write_image erase unlock obj/sd2snes.bin 0
reset run
shutdown

143
src/tests/fpga.c Normal file
View File

@@ -0,0 +1,143 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
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
fpga.c: FPGA (re)configuration
*/
/*
FPGA pin mapping
================
CCLK P0.11 out
PROG_B P1.15 out
INIT_B P2.9 in
DIN P2.8 out
DONE P0.22 in
*/
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "bits.h"
#include "fpga.h"
#include "fpga_spi.h"
#include "config.h"
#include "uart.h"
#include "diskio.h"
#include "integer.h"
#include "ff.h"
#include "fileops.h"
#include "spi.h"
#include "led.h"
#include "timer.h"
#include "rle.h"
void fpga_set_prog_b(uint8_t val) {
if(val)
BITBAND(PROGBREG->FIOSET, PROGBBIT) = 1;
else
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() {
return BITBAND(INITBREG->FIOPIN, INITBBIT);
}
void fpga_init() {
/* mainly GPIO directions */
BITBAND(CCLKREG->FIODIR, CCLKBIT) = 1; /* CCLK */
BITBAND(DONEREG->FIODIR, DONEBIT) = 0; /* DONE */
BITBAND(PROGBREG->FIODIR, PROGBBIT) = 1; /* PROG_B */
BITBAND(DINREG->FIODIR, DINBIT) = 1; /* DIN */
BITBAND(INITBREG->FIODIR, INITBBIT) = 0; /* INIT_B */
LPC_GPIO2->FIOMASK1 = 0;
SPI_OFFLOAD=0;
fpga_set_cclk(0); /* initial clk=0 */
}
int fpga_get_done(void) {
return BITBAND(DONEREG->FIOPIN, DONEBIT);
}
void fpga_postinit() {
LPC_GPIO2->FIOMASK1 = 0;
}
void fpga_pgm(uint8_t* filename) {
int MAXRETRIES = 10;
int retries = MAXRETRIES;
uint8_t data;
int i;
tick_t timeout;
do {
i=0;
timeout = getticks() + 100;
fpga_set_prog_b(0);
uart_putc('P');
fpga_set_prog_b(1);
while(!fpga_get_initb()){
if(getticks() > timeout) {
printf("no response from FPGA trying to initiate configuration!\n");
led_panic();
}
};
LPC_GPIO2->FIOMASK1 = ~(BV(0));
uart_putc('p');
/* open configware file */
file_open(filename, FA_READ);
if(file_res) {
uart_putc('?');
uart_putc(0x30+file_res);
return;
}
uart_putc('C');
for (;;) {
data = rle_file_getc();
i++;
if (file_status || file_res) break; /* error or eof */
FPGA_SEND_BYTE_SERIAL(data);
}
uart_putc('c');
file_close();
printf("fpga_pgm: %d bytes programmed\n", i);
delay_ms(1);
} while (!fpga_get_done() && retries--);
if(!fpga_get_done()) {
printf("FPGA failed to configure after %d tries.\n", MAXRETRIES);
led_panic();
}
printf("FPGA configured\n");
fpga_postinit();
}

68
src/tests/fpga.h Normal file
View File

@@ -0,0 +1,68 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
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
fpga.h: FPGA (re)configuration
*/
#ifndef FPGA_H
#define FPGA_H
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "bits.h"
void fpga_set_prog_b(uint8_t val);
void fpga_set_cclk(uint8_t val);
int fpga_get_initb(void);
void fpga_init(void);
void fpga_postinit(void);
void fpga_pgm(uint8_t* filename);
uint8_t SPI_OFFLOAD;
#define CCLKREG LPC_GPIO0
#define PROGBREG LPC_GPIO1
#define INITBREG LPC_GPIO2
#define DINREG LPC_GPIO2
#define DONEREG LPC_GPIO0
#define CCLKBIT (11)
#define PROGBBIT (15)
#define INITBBIT (9)
#define DINBIT (8)
#define DONEBIT (22)
#define FPGA_TEST_TOKEN (0xa5)
// some macros for bulk transfers (faster)
#define FPGA_SEND_BYTE_SERIAL(data) do {SET_FPGA_DIN(data>>7); CCLK();\
SET_FPGA_DIN(data>>6); CCLK(); SET_FPGA_DIN(data>>5); CCLK();\
SET_FPGA_DIN(data>>4); CCLK(); SET_FPGA_DIN(data>>3); CCLK();\
SET_FPGA_DIN(data>>2); CCLK(); SET_FPGA_DIN(data>>1); CCLK();\
SET_FPGA_DIN(data); CCLK();} while (0)
#define SET_CCLK() do {BITBAND(LPC_GPIO0->FIOSET, 11) = 1;} while (0)
#define CLR_CCLK() do {BITBAND(LPC_GPIO0->FIOCLR, 11) = 1;} while (0)
#define CCLK() do {SET_CCLK(); CLR_CCLK();} while (0)
#define SET_FPGA_DIN(data) do {LPC_GPIO2->FIOPIN1 = data;} while (0)
#endif

528
src/tests/fpga_spi.c Normal file
View File

@@ -0,0 +1,528 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
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
fpga_spi.h: functions for SPI ctrl, SRAM interfacing and feature configuration
*/
/*
SPI commands
cmd param function
=============================================
0t bbhhll set address to 0xbbhhll
t = target
target: 0 = RAM
1 = MSU Audio buffer
2 = MSU Data buffer
targets 1 & 2 only require 2 address bytes to
be written.
10 bbhhll set SNES input address mask to 0xbbhhll
20 bbhhll set SRAM address mask to 0xbbhhll
3m - set mapper to m
0=HiROM, 1=LoROM, 2=ExHiROM, 6=SF96, 7=Menu
4s - trigger SD DMA (512b from SD to memory)
s: Bit 2 = partial, Bit 1:0 = target
target: see above
60 sssseeee set SD DMA partial transfer start+end
ssss = start offset (msb first)
eeee = end offset (msb first)
8p - read (RAM only)
p: 0 = no increment after read
8 = increment after read
9p {xx}* write xx
p: i-tt
tt = target (see above)
i = increment (see above)
E0 ssrr set MSU-1 status register (=FPGA status [7:0])
ss = bits to set in status register (1=set)
rr = bits to reset in status register (1=reset)
E1 - pause DAC
E2 - resume/play DAC
E3 - reset DAC playback pointer (0)
E4 hhll set MSU read pointer
E5 tt{7} set RTC (SPC7110 format + 1000s of year,
nibbles packed)
eg 0x20111210094816 is 2011-12-10, 9:48:16
E6 ssrr set/reset BS-X status register [7:0]
E7 - reset SRTC state
E8 - reset DSP program and data ROM write pointers
E9 hhmmllxxxx write+incr. DSP program ROM (xxxx=dummy writes)
EA hhllxxxx write+incr. DSP data ROM (xxxx=dummy writes)
EB - put DSP into reset
EC - release DSP from reset
ED - set feature enable bits (see below)
EE - select memory (0: ROM (PSRAM), 1: RAM (SRAM))
F0 - receive test token (to see if FPGA is alive)
F1 - receive status (16bit, MSB first), see below
F2 - get MSU data address (32bit, MSB first)
F3 - get MSU audio track no. (16bit, MSB first)
F4 - get MSU volume (8bit)
FE - get SNES master clock frequency (32bit, MSB first)
measured 1x/sec
FF {xx}* echo (returns the sent data in the next byte)
FPGA status word:
bit function
==========================================================================
15 SD DMA busy (0=idle, 1=busy)
14 DAC read pointer MSB
13 MSU read pointer MSB
12 [TODO SD DMA CRC status (0=ok, 1=error); valid after bit 15 -> 0]
11 reserved (0)
10 reserved (0)
9 reserved (0)
8 reserved (0)
7 reserved (0)
6 reserved (0)
5 MSU1 Audio request from SNES
4 MSU1 Data request from SNES
3 reserved (0)
2 MSU1 Audio control status: 0=no repeat, 1=repeat
1 MSU1 Audio control status: 0=pause, 1=play
0 MSU1 Audio control request
FPGA feature enable bits:
bit function
==========================================================================
7 -
6 -
5 -
4 -
3 enable MSU1 registers
2 enable SRTC registers
1 enable ST0010 mapping
0 enable DSPx mapping
*/
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "bits.h"
#include "fpga.h"
#include "config.h"
#include "uart.h"
#include "spi.h"
#include "fpga_spi.h"
#include "timer.h"
#include "sdnative.h"
void fpga_spi_init(void) {
spi_init(SPI_SPEED_FAST);
BITBAND(FPGA_MCU_RDY_REG->FIODIR, FPGA_MCU_RDY_BIT) = 0;
}
void set_msu_addr(uint16_t address) {
FPGA_SELECT();
FPGA_TX_BYTE(0x02);
FPGA_TX_BYTE((address>>8)&0xff);
FPGA_TX_BYTE((address)&0xff);
FPGA_DESELECT();
}
void set_dac_addr(uint16_t address) {
FPGA_SELECT();
FPGA_TX_BYTE(0x01);
FPGA_TX_BYTE((address>>8)&0xff);
FPGA_TX_BYTE((address)&0xff);
FPGA_DESELECT();
}
void set_mcu_addr(uint32_t address) {
FPGA_SELECT();
FPGA_TX_BYTE(0x00);
FPGA_TX_BYTE((address>>16)&0xff);
FPGA_TX_BYTE((address>>8)&0xff);
FPGA_TX_BYTE((address)&0xff);
FPGA_DESELECT();
}
void set_saveram_mask(uint32_t mask) {
FPGA_SELECT();
FPGA_TX_BYTE(0x20);
FPGA_TX_BYTE((mask>>16)&0xff);
FPGA_TX_BYTE((mask>>8)&0xff);
FPGA_TX_BYTE((mask)&0xff);
FPGA_DESELECT();
}
void set_rom_mask(uint32_t mask) {
FPGA_SELECT();
FPGA_TX_BYTE(0x10);
FPGA_TX_BYTE((mask>>16)&0xff);
FPGA_TX_BYTE((mask>>8)&0xff);
FPGA_TX_BYTE((mask)&0xff);
FPGA_DESELECT();
}
void set_mapper(uint8_t val) {
FPGA_SELECT();
FPGA_TX_BYTE(0x30 | (val & 0x0f));
FPGA_DESELECT();
}
uint8_t fpga_test() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF0); /* TEST */
FPGA_TX_BYTE(0x00); /* dummy */
uint8_t result = FPGA_RX_BYTE();
FPGA_DESELECT();
return result;
}
uint16_t fpga_status() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF1); /* STATUS */
FPGA_TX_BYTE(0x00); /* dummy */
uint16_t result = (FPGA_RX_BYTE()) << 8;
result |= FPGA_RX_BYTE();
FPGA_DESELECT();
return result;
}
void fpga_set_sddma_range(uint16_t start, uint16_t end) {
FPGA_SELECT();
FPGA_TX_BYTE(0x60); /* DMA_RANGE */
FPGA_TX_BYTE(start>>8);
FPGA_TX_BYTE(start&0xff);
FPGA_TX_BYTE(end>>8);
FPGA_TX_BYTE(end&0xff);
//if(tgt==1 && (test=FPGA_RX_BYTE()) != 0x41) printf("!!!!!!!!!!!!!!! -%02x- \n", test);
FPGA_DESELECT();
}
void fpga_sddma(uint8_t tgt, uint8_t partial) {
uint32_t test = 0;
uint8_t status = 0;
BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 0;
FPGA_SELECT();
FPGA_TX_BYTE(0x40 | (tgt & 0x3) | ((partial & 1) << 2) ); /* DO DMA */
FPGA_TX_BYTE(0x00); /* dummy for falling DMA_EN edge */
//if(tgt==1 && (test=FPGA_RX_BYTE()) != 0x41) printf("!!!!!!!!!!!!!!! -%02x- \n", test);
FPGA_DESELECT();
FPGA_SELECT();
FPGA_TX_BYTE(0xF1); /* STATUS */
FPGA_TX_BYTE(0x00); /* dummy */
DBG_SD printf("FPGA DMA request sent, wait for completion...");
while((status=FPGA_RX_BYTE()) & 0x80) {
FPGA_RX_BYTE(); /* eat the 2nd status byte */
test++;
}
DBG_SD printf("...complete\n");
FPGA_DESELECT();
if(test<5)printf("loopy: %ld %02x\n", test, status);
BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1;
}
void set_dac_vol(uint8_t volume) {
FPGA_SELECT();
FPGA_TX_BYTE(0x50);
FPGA_TX_BYTE(volume);
FPGA_TX_BYTE(0x00); /* latch rise */
FPGA_TX_BYTE(0x00); /* latch fall */
FPGA_DESELECT();
}
void dac_play() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe2);
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_DESELECT();
}
void dac_pause() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe1);
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_DESELECT();
}
void dac_reset() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe3);
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_DESELECT();
}
void msu_reset(uint16_t address) {
FPGA_SELECT();
FPGA_TX_BYTE(0xe4);
FPGA_TX_BYTE((address>>8) & 0xff); /* address hi */
FPGA_TX_BYTE(address & 0xff); /* address lo */
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_DESELECT();
}
void set_msu_status(uint8_t set, uint8_t reset) {
FPGA_SELECT();
FPGA_TX_BYTE(0xe0);
FPGA_TX_BYTE(set);
FPGA_TX_BYTE(reset);
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_DESELECT();
}
uint8_t get_msu_volume() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF4); /* MSU_VOLUME */
FPGA_TX_BYTE(0x00); /* dummy */
uint8_t result = FPGA_RX_BYTE();
FPGA_DESELECT();
return result;
}
uint16_t get_msu_track() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF3); /* MSU_TRACK */
FPGA_TX_BYTE(0x00); /* dummy */
uint16_t result = (FPGA_RX_BYTE()) << 8;
result |= FPGA_RX_BYTE();
FPGA_DESELECT();
return result;
}
uint32_t get_msu_offset() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF2); /* MSU_OFFSET */
FPGA_TX_BYTE(0x00); /* dummy */
uint32_t result = (FPGA_RX_BYTE()) << 24;
result |= (FPGA_RX_BYTE()) << 16;
result |= (FPGA_RX_BYTE()) << 8;
result |= (FPGA_RX_BYTE());
FPGA_DESELECT();
return result;
}
uint32_t get_snes_romselclk() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF7);
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(0x00); /* dummy */
uint32_t result = (FPGA_RX_BYTE()) << 24;
result |= (FPGA_RX_BYTE()) << 16;
result |= (FPGA_RX_BYTE()) << 8;
result |= (FPGA_RX_BYTE());
FPGA_DESELECT();
return result;
}
uint32_t get_snes_cpuclk() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF8);
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(0x00); /* dummy */
uint32_t result = (FPGA_RX_BYTE()) << 24;
result |= (FPGA_RX_BYTE()) << 16;
result |= (FPGA_RX_BYTE()) << 8;
result |= (FPGA_RX_BYTE());
FPGA_DESELECT();
return result;
}
uint32_t get_snes_readclk() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF9);
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(0x00); /* dummy */
uint32_t result = (FPGA_RX_BYTE()) << 24;
result |= (FPGA_RX_BYTE()) << 16;
result |= (FPGA_RX_BYTE()) << 8;
result |= (FPGA_RX_BYTE());
FPGA_DESELECT();
return result;
}
uint32_t get_snes_writeclk() {
FPGA_SELECT();
FPGA_TX_BYTE(0xFA); /* GET_SYSCLK */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(0x00); /* dummy */
uint32_t result = (FPGA_RX_BYTE()) << 24;
result |= (FPGA_RX_BYTE()) << 16;
result |= (FPGA_RX_BYTE()) << 8;
result |= (FPGA_RX_BYTE());
FPGA_DESELECT();
return result;
}
uint32_t get_snes_pardclk() {
FPGA_SELECT();
FPGA_TX_BYTE(0xFB); /* GET_SYSCLK */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(0x00); /* dummy */
uint32_t result = (FPGA_RX_BYTE()) << 24;
result |= (FPGA_RX_BYTE()) << 16;
result |= (FPGA_RX_BYTE()) << 8;
result |= (FPGA_RX_BYTE());
FPGA_DESELECT();
return result;
}
uint32_t get_snes_pawrclk() {
FPGA_SELECT();
FPGA_TX_BYTE(0xFC); /* GET_SYSCLK */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(0x00); /* dummy */
uint32_t result = (FPGA_RX_BYTE()) << 24;
result |= (FPGA_RX_BYTE()) << 16;
result |= (FPGA_RX_BYTE()) << 8;
result |= (FPGA_RX_BYTE());
FPGA_DESELECT();
return result;
}
uint32_t get_snes_refreshclk() {
FPGA_SELECT();
FPGA_TX_BYTE(0xFD); /* GET_SYSCLK */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(0x00); /* dummy */
uint32_t result = (FPGA_RX_BYTE()) << 24;
result |= (FPGA_RX_BYTE()) << 16;
result |= (FPGA_RX_BYTE()) << 8;
result |= (FPGA_RX_BYTE());
FPGA_DESELECT();
return result;
}
uint32_t get_snes_sysclk() {
FPGA_SELECT();
FPGA_TX_BYTE(0xFE); /* GET_SYSCLK */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(0x00); /* dummy */
uint32_t result = (FPGA_RX_BYTE()) << 24;
result |= (FPGA_RX_BYTE()) << 16;
result |= (FPGA_RX_BYTE()) << 8;
result |= (FPGA_RX_BYTE());
FPGA_DESELECT();
return result;
}
void set_bsx_regs(uint8_t set, uint8_t reset) {
FPGA_SELECT();
FPGA_TX_BYTE(0xe6);
FPGA_TX_BYTE(set);
FPGA_TX_BYTE(reset);
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_DESELECT();
}
void set_fpga_time(uint64_t time) {
FPGA_SELECT();
FPGA_TX_BYTE(0xe5);
FPGA_TX_BYTE((time >> 48) & 0xff);
FPGA_TX_BYTE((time >> 40) & 0xff);
FPGA_TX_BYTE((time >> 32) & 0xff);
FPGA_TX_BYTE((time >> 24) & 0xff);
FPGA_TX_BYTE((time >> 16) & 0xff);
FPGA_TX_BYTE((time >> 8) & 0xff);
FPGA_TX_BYTE(time & 0xff);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
void fpga_reset_srtc_state() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe7);
FPGA_TX_BYTE(0x00);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
void fpga_reset_dspx_addr() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe8);
FPGA_TX_BYTE(0x00);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
void fpga_write_bram_data(uint8_t data) {
FPGA_SELECT();
FPGA_TX_BYTE(0xe9);
FPGA_TX_BYTE(data);
FPGA_TX_BYTE(0x00);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
void fpga_write_dspx_dat(uint16_t data) {
FPGA_SELECT();
FPGA_TX_BYTE(0xea);
FPGA_TX_BYTE((data>>8)&0xff);
FPGA_TX_BYTE((data)&0xff);
FPGA_TX_BYTE(0x00);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
void fpga_dspx_reset(uint8_t reset) {
FPGA_SELECT();
FPGA_TX_BYTE(reset ? 0xeb : 0xec);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
void fpga_set_features(uint8_t feat) {
FPGA_SELECT();
FPGA_TX_BYTE(0xed);
FPGA_TX_BYTE(feat);
FPGA_DESELECT();
}
void fpga_select_mem(uint8_t unit) {
FPGA_SELECT();
FPGA_TX_BYTE(0xee);
FPGA_TX_BYTE(unit);
FPGA_DESELECT();
}
void fpga_set_bram_addr(uint16_t addr) {
FPGA_SELECT();
FPGA_TX_BYTE(0xe8);
FPGA_TX_BYTE((addr>>8)&0xff);
FPGA_TX_BYTE((addr)&0xff);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
uint8_t fpga_read_bram_data() {
uint8_t data;
FPGA_SELECT();
FPGA_TX_BYTE(0xf5);
FPGA_TX_BYTE(0x00);
data = FPGA_RX_BYTE();
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
return data;
}

104
src/tests/fpga_spi.h Normal file
View File

@@ -0,0 +1,104 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
uC firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
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
fpga_spi.h: functions for SPI ctrl, SRAM interfacing and feature configuration
*/
#ifndef _FPGA_SPI_H
#define _FPGA_SPI_H
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "bits.h"
#include "spi.h"
#include "config.h"
#define FPGA_SS_BIT 16
#define FPGA_SS_REG LPC_GPIO0
#define FPGA_SELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOCLR, FPGA_SS_BIT) = 1;} while (0)
#define FPGA_SELECT_ASYNC() do {BITBAND(FPGA_SS_REG->FIOCLR, FPGA_SS_BIT) = 1;} while (0)
#define FPGA_DESELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOSET, FPGA_SS_BIT) = 1;} while (0)
#define FPGA_DESELECT_ASYNC() do {BITBAND(FPGA_SS_REG->FIOSET, FPGA_SS_BIT) = 1;} while (0)
#define FPGA_TX_SYNC() spi_tx_sync()
#define FPGA_TX_BYTE(x) spi_tx_byte(x)
#define FPGA_RX_BYTE() spi_rx_byte()
#define FPGA_TXRX_BYTE(x) spi_txrx_byte(x)
#define FPGA_TX_BLOCK(x,y) spi_tx_block(x,y)
#define FPGA_RX_BLOCK(x,y) spi_rx_block(x,y)
#define FPGA_SPI_FAST() spi_set_speed(SPI_SPEED_FPGA_FAST)
#define FPGA_SPI_SLOW() spi_set_speed(SPI_SPEED_FPGA_SLOW)
#define FEAT_CX4 (1 << 4)
#define FEAT_MSU1 (1 << 3)
#define FEAT_SRTC (1 << 2)
#define FEAT_ST0010 (1 << 1)
#define FEAT_DSPX (1 << 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)
void fpga_spi_init(void);
uint8_t fpga_test(void);
uint16_t fpga_status(void);
void spi_fpga(void);
void spi_sd(void);
void spi_none(void);
void set_mcu_addr(uint32_t);
void set_dac_addr(uint16_t);
void set_dac_vol(uint8_t);
void dac_play(void);
void dac_pause(void);
void dac_reset(void);
void msu_reset(uint16_t);
void set_msu_addr(uint16_t);
void set_msu_status(uint8_t set, uint8_t reset);
void set_saveram_mask(uint32_t);
void set_rom_mask(uint32_t);
void set_mapper(uint8_t val);
void fpga_sddma(uint8_t tgt, uint8_t partial);
void fpga_set_sddma_range(uint16_t start, uint16_t end);
uint8_t get_msu_volume(void);
uint16_t get_msu_track(void);
uint32_t get_msu_offset(void);
uint32_t get_snes_sysclk(void);
uint32_t get_snes_readclk(void);
uint32_t get_snes_writeclk(void);
uint32_t get_snes_pardclk(void);
uint32_t get_snes_pawrclk(void);
uint32_t get_snes_refreshclk(void);
uint32_t get_snes_cpuclk(void);
uint32_t get_snes_romselclk(void);
void set_bsx_regs(uint8_t set, uint8_t reset);
void set_fpga_time(uint64_t time);
void fpga_reset_srtc_state(void);
void fpga_reset_dspx_addr(void);
void fpga_write_dspx_pgm(uint32_t data);
void fpga_write_dspx_dat(uint16_t data);
void fpga_dspx_reset(uint8_t reset);
void fpga_set_features(uint8_t feat);
void fpga_select_mem(uint8_t unit);
void fpga_set_bram_addr(uint16_t addr);
uint8_t fpga_read_bram_data(void);
void fpga_write_bram_data(uint8_t data);
#endif

37
src/tests/integer.h Normal file
View File

@@ -0,0 +1,37 @@
/*-------------------------------------------*/
/* Integer type definitions for FatFs module */
/*-------------------------------------------*/
#ifndef _INTEGER
#define _INTEGER
#ifdef _WIN32 /* FatFs development platform */
#include <windows.h>
#include <tchar.h>
#else /* Embedded platform */
/* These types must be 16-bit, 32-bit or larger integer */
typedef int INT;
typedef unsigned int UINT;
/* These types must be 8-bit integer */
typedef char CHAR;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;
/* These types must be 16-bit integer */
typedef short SHORT;
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
/* These types must be 32-bit integer */
typedef long LONG;
typedef unsigned long ULONG;
typedef unsigned long DWORD;
#endif
#endif

15
src/tests/irq.c Normal file
View File

@@ -0,0 +1,15 @@
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "bits.h"
#include "config.h"
#include "sdnative.h"
#include "uart.h"
void EINT3_IRQHandler(void) {
NVIC_ClearPendingIRQ(EINT3_IRQn);
if(SD_CHANGE_DETECT) {
SD_CHANGE_CLR();
sdn_changed();
}
}

145
src/tests/led.c Normal file
View File

@@ -0,0 +1,145 @@
/* ___DISCLAIMER___ */
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "bits.h"
#include "timer.h"
#include "led.h"
#include "cli.h"
static uint8_t led_bright[16]={255,253,252,251,249,247,244,239,232,223,210,191,165,127,74,0};
int led_rdyledstate = 0;
int led_readledstate = 0;
int led_writeledstate = 0;
int led_pwmstate = 0;
/* LED connections (Rev.C)
LED color IO PWM
---------------------------
ready green P2.4 PWM1[5]
read yellow P2.5 PWM1[6]
write red P1.23 PWM1[4]
*/
void rdyled(unsigned int state) {
if(led_pwmstate) {
rdybright(state?15:0);
} else {
BITBAND(LPC_GPIO2->FIODIR, 4) = state;
}
led_rdyledstate = state;
}
void readled(unsigned int state) {
if(led_pwmstate) {
readbright(state?15:0);
} else {
BITBAND(LPC_GPIO2->FIODIR, 5) = state;
}
led_readledstate = state;
}
void writeled(unsigned int state) {
if(led_pwmstate) {
writebright(state?15:0);
} else {
BITBAND(LPC_GPIO1->FIODIR, 23) = state;
}
led_writeledstate = state;
}
void rdybright(uint8_t bright) {
LPC_PWM1->MR5 = led_bright[(bright & 15)];
BITBAND(LPC_PWM1->LER, 5) = 1;
}
void readbright(uint8_t bright) {
LPC_PWM1->MR6 = led_bright[(bright & 15)];
BITBAND(LPC_PWM1->LER, 6) = 1;
}
void writebright(uint8_t bright) {
LPC_PWM1->MR4 = led_bright[(bright & 15)];
BITBAND(LPC_PWM1->LER, 4) = 1;
}
void led_clkout32(uint32_t val) {
while(1) {
rdyled(1);
delay_ms(400);
readled((val & BV(31))>>31);
rdyled(0);
val<<=1;
delay_ms(400);
}
}
void toggle_rdy_led() {
rdyled(~led_rdyledstate);
}
void toggle_read_led() {
readled(~led_readledstate);
}
void toggle_write_led() {
writeled(~led_writeledstate);
}
void led_panic() {
while(1) {
LPC_GPIO2->FIODIR |= BV(4) | BV(5);
LPC_GPIO1->FIODIR |= BV(23);
delay_ms(350);
LPC_GPIO2->FIODIR &= ~(BV(4) | BV(5));
LPC_GPIO1->FIODIR &= ~BV(23);
delay_ms(350);
cli_entrycheck();
}
}
void led_pwm() {
/* Rev.C P2.4, P2.5, P1.23 */
BITBAND(LPC_PINCON->PINSEL4, 9) = 0;
BITBAND(LPC_PINCON->PINSEL4, 8) = 1;
BITBAND(LPC_PINCON->PINSEL4, 11) = 0;
BITBAND(LPC_PINCON->PINSEL4, 10) = 1;
BITBAND(LPC_PINCON->PINSEL3, 15) = 1;
BITBAND(LPC_PINCON->PINSEL3, 14) = 0;
BITBAND(LPC_PWM1->PCR, 12) = 1;
BITBAND(LPC_PWM1->PCR, 13) = 1;
BITBAND(LPC_PWM1->PCR, 14) = 1;
led_pwmstate = 1;
}
void led_std() {
BITBAND(LPC_PINCON->PINSEL4, 9) = 0;
BITBAND(LPC_PINCON->PINSEL4, 8) = 0;
BITBAND(LPC_PINCON->PINSEL4, 11) = 0;
BITBAND(LPC_PINCON->PINSEL4, 10) = 0;
BITBAND(LPC_PINCON->PINSEL3, 15) = 0;
BITBAND(LPC_PINCON->PINSEL3, 14) = 0;
BITBAND(LPC_PWM1->PCR, 12) = 0;
BITBAND(LPC_PWM1->PCR, 13) = 0;
BITBAND(LPC_PWM1->PCR, 14) = 0;
led_pwmstate = 0;
}
void led_init() {
/* power is already connected by default */
/* set PCLK divider to 8 */
BITBAND(LPC_SC->PCLKSEL0, 13) = 1;
BITBAND(LPC_SC->PCLKSEL0, 12) = 1;
LPC_PWM1->MR0 = 255;
BITBAND(LPC_PWM1->LER, 0) = 1;
BITBAND(LPC_PWM1->TCR, 0) = 1;
BITBAND(LPC_PWM1->TCR, 3) = 1;
BITBAND(LPC_PWM1->MCR, 1) = 1;
}

21
src/tests/led.h Normal file
View File

@@ -0,0 +1,21 @@
/* ___DISCLAIMER___ */
#ifndef _LED_H
#define _LED_H
void readbright(uint8_t bright);
void writebright(uint8_t bright);
void rdybright(uint8_t bright);
void readled(unsigned int state);
void writeled(unsigned int state);
void rdyled(unsigned int state);
void led_clkout32(uint32_t val);
void toggle_rdy_led(void);
void toggle_read_led(void);
void toggle_write_led(void);
void led_panic(void);
void led_pwm(void);
void led_std(void);
void led_init(void);
#endif

77
src/tests/lpc1754.cfg Normal file
View File

@@ -0,0 +1,77 @@
# NXP LPC1754 Cortex-M3 with 128kB Flash and 16kB+16kB Local On-Chip SRAM,
# reset_config trst_and_srst
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME lpc1754
}
# After reset the chip is clocked by the ~4MHz internal RC oscillator.
# When board-specific code (reset-init handler or device firmware)
# configures another oscillator and/or PLL0, set CCLK to match; if
# you don't, then flash erase and write operations may misbehave.
# (The ROM code doing those updates cares about core clock speed...)
#
# CCLK is the core clock frequency in KHz
if { [info exists CCLK ] } {
set _CCLK $CCLK
} else {
set _CCLK 4000
}
if { [info exists CPUTAPID ] } {
set _CPUTAPID $CPUTAPID
} else {
set _CPUTAPID 0x4ba00477
}
#delays on reset lines
#if your OpenOCD version rejects "jtag_nsrst_delay" replace it with:
#adapter_nsrst_delay 200
jtag_nsrst_delay 200
jtag_ntrst_delay 200
# LPC2000 & LPC1700 -> SRST causes TRST
#reset_config srst_pulls_trst
reset_config trst_and_srst srst_push_pull trst_push_pull
jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID
#jtag newtap x3s tap -irlen 6 -ircapture 0x11 -irmask 0x11 -expected-id 0x0141c093
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m3 -chain-position $_TARGETNAME -event reset-init 0
# 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).
$_TARGETNAME configure -work-area-phys 0x10000000 -work-area-size 0x4000
$_TARGETNAME configure -work-area-phys 0x2007c000 -work-area-size 0x4000
# LPC1754 has 128kB of flash memory, managed by ROM code (including a
# boot loader which verifies the flash exception table's checksum).
# flash bank <name> lpc2000 <base> <size> 0 0 <target#> <variant> <clock> [calc checksum]
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME lpc2000 0x0 0x20000 0 0 $_TARGETNAME \
lpc1700 $_CCLK calc_checksum
# Run with *real slow* clock by default since the
# boot rom could have been playing with the PLL, so
# we have no idea what clock the target is running at.
jtag_khz 1000
$_TARGETNAME configure -event reset-init {
# Do not remap 0x0000-0x0020 to anything but the flash (i.e. select
# "User Flash Mode" where interrupt vectors are _not_ remapped,
# and reside in flash instead).
#
# See Table 612. Memory Mapping Control register (MEMMAP - 0x400F C040) bit description
# Bit Symbol Value Description Reset
# value
# 0 MAP Memory map control. 0
# 0 Boot mode. A portion of the Boot ROM is mapped to address 0.
# 1 User mode. The on-chip Flash memory is mapped to address 0.
# 31:1 - Reserved. The value read from a reserved bit is not defined. NA
#
# http://ics.nxp.com/support/documents/microcontrollers/?scope=LPC1768&type=user
mww 0x400FC040 0x01
}

131
src/tests/lpc1754.ld Normal file
View File

@@ -0,0 +1,131 @@
/* Linker script for LPC1754
*
* Written 2010 by Ingo Korb
*
* Partially based on the linker scripts of avr-libc
*/
OUTPUT_FORMAT(elf32-littlearm)
ENTRY(_start)
MEMORY
{
flash (rx) : ORIGIN = 0x00000000, LENGTH = 0x20000 /* leave room for bootldr + metadata */
ram (rwx) : ORIGIN = 0x10000000, LENGTH = 0x04000
ahbram (rwx) : ORIGIN = 0x2007C000, LENGTH = 0x04000
}
SECTIONS
{
.text :
{
KEEP(*(.vectors))
KEEP(*(.init))
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
/* C++ con-/destructors */
__ctors_start = . ;
*(.ctors)
__ctors_end = . ;
__dtors_start = . ;
*(.dtors)
__dtors_end = . ;
KEEP(SORT(*)(.ctors))
KEEP(SORT(*)(.dtors))
KEEP(*(.fini))
__text_end = .;
} > flash
/* .ARM.exidx is sorted, so has to go in its own output section. */
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} >flash
__exidx_end = .;
/* I hope this does what I think it does */
.rodata : AT (ALIGN(__exidx_end,4))
{
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
__rodata_end = .;
} > flash
/* Data section */
.data : AT (ALIGN(__rodata_end,4))
{
__data_start = .;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
__data_end = .;
} > ram
/* Addresses of in-rom data section */
__data_load_start = LOADADDR(.data);
__data_load_end = __data_load_start + SIZEOF(.data);
. = ALIGN(4);
/* BSS */
.bss :
{
__bss_start__ = .;
*(.bss)
*(.bss.*)
*(COMMON)
__bss_end__ = .;
} > ram
/* second BSS in AHB ram */
.ahbram (NOLOAD) :
{
__ahbram_start__ = .;
*(.ahbram)
*(.ahbram.*)
__ahbram_end__ = .;
} > ahbram
__heap_start = ALIGN(__bss_end__, 4);
/* Default stack starts at end of ram */
PROVIDE(__stack = ORIGIN(ram) + LENGTH(ram)) ;
/* Everyone seems to copy the stuff below straight from somewhere else, so I'll do that too */
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
}

164
src/tests/main.c Normal file
View File

@@ -0,0 +1,164 @@
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include <string.h>
#include "config.h"
#include "obj/autoconf.h"
#include "clock.h"
#include "uart.h"
#include "bits.h"
#include "power.h"
#include "timer.h"
#include "ff.h"
#include "diskio.h"
#include "spi.h"
#include "fileops.h"
#include "fpga.h"
#include "fpga_spi.h"
#include "filetypes.h"
#include "memory.h"
#include "snes.h"
#include "led.h"
#include "sort.h"
#include "cic.h"
#include "tests.h"
#include "cli.h"
#include "sdnative.h"
#include "crc.h"
#include "smc.h"
#include "msu1.h"
#include "rtc.h"
#include "tests.h"
#define EMC0TOGGLE (3<<4)
#define MR0R (1<<1)
int i;
int sd_offload = 0, ff_sd_offload = 0, sd_offload_tgt = 0;
int sd_offload_partial = 0;
uint16_t sd_offload_partial_start = 0;
uint16_t sd_offload_partial_end = 0;
volatile enum diskstates disk_state;
extern volatile tick_t ticks;
extern snes_romprops_t romprops;
extern volatile int reset_changed;
enum system_states {
SYS_RTC_STATUS = 0
};
int main(void) {
LPC_GPIO2->FIODIR = BV(4) | BV(5);
LPC_GPIO1->FIODIR = BV(23) | BV(SNES_CIC_PAIR_BIT);
BITBAND(SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT) = 1;
LPC_GPIO0->FIODIR = BV(16);
/* connect UART3 on P0[25:26] + SSP0 on P0[15:18] + MAT3.0 on P0[10] */
LPC_PINCON->PINSEL1 = BV(18) | BV(19) | BV(20) | BV(21) /* UART3 */
| BV(3) | BV(5); /* SSP0 (FPGA) except SS */
LPC_PINCON->PINSEL0 = BV(31); /* SSP0 */
/* | BV(13) | BV(15) | BV(17) | BV(19) SSP1 (SD) */
/* pull-down CIC data lines */
LPC_PINCON->PINMODE0 = BV(0) | BV(1) | BV(2) | BV(3);
clock_disconnect();
snes_init();
snes_reset(1);
power_init();
timer_init();
uart_init();
fpga_spi_init();
spi_preinit();
led_init();
/* do this last because the peripheral init()s change PCLK dividers */
clock_init();
LPC_PINCON->PINSEL0 |= BV(20) | BV(21); /* MAT3.0 (FPGA clock) */
led_pwm();
sdn_init();
printf("\n\nsd2snes mk.2\n============\nfw ver.: " VER "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY);
printf("PCONP=%lx\n", LPC_SC->PCONP);
file_init();
cic_init(0);
/* setup timer (fpga clk) */
LPC_TIM3->CTCR=0;
LPC_TIM3->EMR=EMC0TOGGLE;
LPC_TIM3->MCR=MR0R;
LPC_TIM3->MR0=1;
LPC_TIM3->TCR=1;
fpga_init();
char *testnames[11] = { "SD ", "USB ", "RTC ", "CIC ",
"FPGA ", "RAM ", "CLK ", "DAC ",
"SNES IRQ", "SNES RAM", "SNES PA "};
char *teststate_names [3] = { "no run", "\x1b[32;1mPassed\x1b[m", "\x1b[31;1mFAILED\x1b[m" };
int testresults[11] = { NO_RUN, NO_RUN, NO_RUN, NO_RUN, NO_RUN,
NO_RUN, NO_RUN, NO_RUN, NO_RUN, NO_RUN,
NO_RUN };
testresults[TEST_SD] = test_sd();
//testresults[TEST_USB] = test_usb();
testresults[TEST_RTC] = test_rtc();
delay_ms(209);
testresults[TEST_CIC] = test_cic();
testresults[TEST_FPGA] = test_fpga();
testresults[TEST_RAM] = test_mem();
printf("Loading SNES test ROM\n=====================\n");
load_rom((uint8_t*)"/sd2snes/test.bin", 0, LOADROM_WITH_RESET);
printf("\n\n\n");
delay_ms(1000);
testresults[TEST_CLK] = test_clk();
fpga_set_bram_addr(0x1fff);
fpga_write_bram_data(0x01); // tell SNES test program to continue
uint8_t snestest_irq_state, snestest_pa_state, snestest_mem_state, snestest_mem_bank;
uint8_t snestest_irq_done = 0, snestest_pa_done = 0, snestest_mem_done = 0;
uint8_t last_irq_state = 0x77, last_pa_state = 0x77, last_mem_state = 0x77, last_mem_bank = 0x77;
uint32_t failed_addr = 0;
while(!(snestest_irq_done & snestest_pa_done & snestest_mem_done)) {
fpga_set_bram_addr(0);
snestest_irq_state = fpga_read_bram_data();
snestest_mem_state = fpga_read_bram_data();
snestest_pa_state = fpga_read_bram_data();
snestest_mem_bank = fpga_read_bram_data();
if(snestest_irq_state != last_irq_state
|| snestest_mem_state != last_mem_state
|| snestest_pa_state != last_pa_state
|| snestest_mem_bank != last_mem_bank) {
printf("SNES test status: IRQ: %02x PA: %02x MEM: %02x/%02x\r", snestest_irq_state, snestest_pa_state, snestest_mem_state, snestest_mem_bank);
}
last_irq_state = snestest_irq_state;
last_mem_state = snestest_mem_state;
last_pa_state = snestest_pa_state;
last_mem_bank = snestest_mem_bank;
if(snestest_pa_state != 0x00) snestest_pa_done = 1;
if(snestest_irq_state != 0x00) snestest_irq_done = 1;
if(snestest_mem_state == 0xff || snestest_mem_state == 0x5a) snestest_mem_done = 1;
cli_entrycheck();
}
printf("\n");
if(snestest_pa_state == 0xff) testresults[TEST_SNES_PA] = FAILED;
else testresults[TEST_SNES_PA] = PASSED;
if(snestest_irq_state == 0xff) testresults[TEST_SNES_IRQ] = FAILED;
else testresults[TEST_SNES_IRQ] = PASSED;
if(snestest_mem_state == 0xff) {
testresults[TEST_SNES_RAM] = FAILED;
fpga_set_bram_addr(4);
failed_addr = fpga_read_bram_data();
failed_addr |= fpga_read_bram_data() << 8;
failed_addr |= fpga_read_bram_data() << 16;
printf("SNES MEM test FAILED (failed address: %06lx)\n", failed_addr);
}
else testresults[TEST_SNES_RAM] = PASSED;
printf("\n\nTEST SUMMARY\n============\n\n");
printf("Test Result\n----------------\n");
int testcount;
for(testcount=0; testcount < 11; testcount++) {
printf("%s %s\n", testnames[testcount], teststate_names[testresults[testcount]]);
}
cli_loop();
while(1);
}

547
src/tests/memory.c Normal file
View File

@@ -0,0 +1,547 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
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
memory.c: RAM operations
*/
#include "config.h"
#include "uart.h"
#include "fpga.h"
#include "crc.h"
#include "crc32.h"
#include "ff.h"
#include "fileops.h"
#include "spi.h"
#include "fpga_spi.h"
#include "led.h"
#include "smc.h"
#include "memory.h"
#include "snes.h"
#include "timer.h"
#include "rle.h"
#include "diskio.h"
#include "msu1.h"
#include <string.h>
char* hex = "0123456789ABCDEF";
extern snes_romprops_t romprops;
void sram_hexdump(uint32_t addr, uint32_t len) {
static uint8_t buf[16];
uint32_t ptr;
for(ptr=0; ptr < len; ptr += 16) {
sram_readblock((void*)buf, ptr+addr, 16);
uart_trace(buf, 0, 16);
}
}
void sram_writebyte(uint8_t val, uint32_t addr) {
set_mcu_addr(addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x98); /* WRITE */
FPGA_TX_BYTE(val);
FPGA_WAIT_RDY();
FPGA_DESELECT();
}
uint8_t sram_readbyte(uint32_t addr) {
set_mcu_addr(addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x88); /* READ */
FPGA_WAIT_RDY();
uint8_t val = FPGA_RX_BYTE();
FPGA_DESELECT();
return val;
}
void sram_writeshort(uint16_t val, uint32_t addr) {
set_mcu_addr(addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x98); /* WRITE */
FPGA_TX_BYTE(val&0xff);
FPGA_WAIT_RDY();
FPGA_TX_BYTE((val>>8)&0xff);
FPGA_WAIT_RDY();
FPGA_DESELECT();
}
void sram_writelong(uint32_t val, uint32_t addr) {
set_mcu_addr(addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x98); /* WRITE */
FPGA_TX_BYTE(val&0xff);
FPGA_WAIT_RDY();
FPGA_TX_BYTE((val>>8)&0xff);
FPGA_WAIT_RDY();
FPGA_TX_BYTE((val>>16)&0xff);
FPGA_WAIT_RDY();
FPGA_TX_BYTE((val>>24)&0xff);
FPGA_WAIT_RDY();
FPGA_DESELECT();
}
uint16_t sram_readshort(uint32_t addr) {
set_mcu_addr(addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x88);
FPGA_WAIT_RDY();
uint32_t val = FPGA_RX_BYTE();
FPGA_WAIT_RDY();
val |= ((uint32_t)FPGA_RX_BYTE()<<8);
FPGA_DESELECT();
return val;
}
uint32_t sram_readlong(uint32_t addr) {
set_mcu_addr(addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x88);
FPGA_WAIT_RDY();
uint32_t val = FPGA_RX_BYTE();
FPGA_WAIT_RDY();
val |= ((uint32_t)FPGA_RX_BYTE()<<8);
FPGA_WAIT_RDY();
val |= ((uint32_t)FPGA_RX_BYTE()<<16);
FPGA_WAIT_RDY();
val |= ((uint32_t)FPGA_RX_BYTE()<<24);
FPGA_DESELECT();
return val;
}
void sram_readlongblock(uint32_t* buf, uint32_t addr, uint16_t count) {
set_mcu_addr(addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x88);
uint16_t i=0;
while(i<count) {
FPGA_WAIT_RDY();
uint32_t val = (uint32_t)FPGA_RX_BYTE()<<24;
FPGA_WAIT_RDY();
val |= ((uint32_t)FPGA_RX_BYTE()<<16);
FPGA_WAIT_RDY();
val |= ((uint32_t)FPGA_RX_BYTE()<<8);
FPGA_WAIT_RDY();
val |= FPGA_RX_BYTE();
buf[i++] = val;
}
FPGA_DESELECT();
}
void sram_readblock(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();
*(tgt++) = FPGA_RX_BYTE();
}
FPGA_DESELECT();
}
void sram_writeblock(void* buf, uint32_t addr, uint16_t size) {
uint16_t count=size;
uint8_t* src = buf;
set_mcu_addr(addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x98); /* WRITE */
while(count--) {
FPGA_TX_BYTE(*src++);
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
}
uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) {
UINT bytes_read;
DWORD filesize;
UINT count=0;
tick_t ticksstart, ticks_total=0;
ticksstart=getticks();
printf("%s\n", filename);
file_open(filename, FA_READ);
if(file_res) {
uart_putc('?');
uart_putc(0x30+file_res);
return 0;
}
filesize = file_handle.fsize;
smc_id(&romprops);
file_close();
/* reconfigure FPGA if necessary */
if(romprops.fpga_conf) {
printf("reconfigure FPGA with %s...\n", romprops.fpga_conf);
fpga_pgm((uint8_t*)romprops.fpga_conf);
}
set_mcu_addr(base_addr);
file_open(filename, FA_READ);
f_lseek(&file_handle, romprops.offset);
for(;;) {
ff_sd_offload=1;
sd_offload_tgt=0;
bytes_read = file_read();
if (file_res || !bytes_read) break;
if(!(count++ % 512)) {
uart_putc('.');
}
}
file_close();
set_mapper(romprops.mapper_id);
printf("rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id);
ticks_total=getticks()-ticksstart;
printf("%u ticks total\n", ticks_total);
if(romprops.mapper_id==3) {
printf("BSX Flash cart image\n");
printf("attempting to load BSX BIOS /sd2snes/bsxbios.bin...\n");
load_sram_offload((uint8_t*)"/sd2snes/bsxbios.bin", 0x800000);
printf("Type: %02x\n", romprops.header.destcode);
set_bsx_regs(0xc0, 0x3f);
uint16_t rombase;
if(romprops.header.ramsize & 1) {
rombase = 0xff00;
// set_bsx_regs(0x36, 0xc9);
} else {
rombase = 0x7f00;
// set_bsx_regs(0x34, 0xcb);
}
sram_writebyte(0x33, rombase+0xda);
sram_writebyte(0x00, rombase+0xd4);
sram_writebyte(0xfc, rombase+0xd5);
set_fpga_time(0x0220110301180530LL);
}
uint32_t rammask;
uint32_t rommask;
while(filesize > (romprops.romsize_bytes + romprops.offset)) {
romprops.romsize_bytes <<= 1;
}
if(romprops.header.ramsize == 0) {
rammask = 0;
} else {
rammask = romprops.ramsize_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);
set_saveram_mask(rammask);
set_rom_mask(rommask);
readled(0);
if(flags & LOADROM_WITH_SRAM) {
if(romprops.ramsize_bytes) {
strcpy(strrchr((char*)filename, (int)'.'), ".srm");
printf("SRM file: %s\n", filename);
load_sram(filename, SRAM_SAVE_ADDR);
} else {
printf("No SRAM\n");
}
}
printf("check MSU...");
if(msu1_check(filename)) {
romprops.fpga_features |= FEAT_MSU1;
romprops.has_msu1 = 1;
} else {
romprops.has_msu1 = 0;
}
printf("done\n");
romprops.fpga_features |= FEAT_SRTC;
fpga_set_features(romprops.fpga_features);
if(flags & LOADROM_WITH_RESET) {
fpga_dspx_reset(1);
snes_reset(1);
delay_ms(10);
snes_reset(0);
fpga_dspx_reset(0);
}
return (uint32_t)filesize;
}
uint32_t load_sram_offload(uint8_t* filename, uint32_t base_addr) {
set_mcu_addr(base_addr);
UINT bytes_read;
DWORD filesize;
file_open(filename, FA_READ);
filesize = file_handle.fsize;
if(file_res) return 0;
for(;;) {
ff_sd_offload=1;
sd_offload_tgt=0;
bytes_read = file_read();
if (file_res || !bytes_read) break;
}
file_close();
return (uint32_t)filesize;
}
uint32_t load_sram(uint8_t* filename, uint32_t base_addr) {
set_mcu_addr(base_addr);
UINT bytes_read;
DWORD filesize;
file_open(filename, FA_READ);
filesize = file_handle.fsize;
if(file_res) {
printf("load_sram: could not open %s, res=%d\n", filename, file_res);
return 0;
}
for(;;) {
bytes_read = file_read();
if (file_res || !bytes_read) break;
FPGA_SELECT();
FPGA_TX_BYTE(0x98);
for(int j=0; j<bytes_read; j++) {
FPGA_TX_BYTE(file_buf[j]);
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
}
file_close();
return (uint32_t)filesize;
}
uint32_t load_sram_rle(uint8_t* filename, uint32_t base_addr) {
uint8_t data;
set_mcu_addr(base_addr);
DWORD filesize;
file_open(filename, FA_READ);
filesize = file_handle.fsize;
if(file_res) return 0;
FPGA_SELECT();
FPGA_TX_BYTE(0x98);
for(;;) {
data = rle_file_getc();
if (file_res || file_status) break;
FPGA_TX_BYTE(data);
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
file_close();
return (uint32_t)filesize;
}
void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr) {
uint32_t count = 0;
uint32_t num = 0;
FPGA_DESELECT();
file_open(filename, FA_CREATE_ALWAYS | FA_WRITE);
if(file_res) {
uart_putc(0x30+file_res);
}
while(count<sram_size) {
set_mcu_addr(base_addr+count);
FPGA_SELECT();
FPGA_TX_BYTE(0x88); /* read */
for(int j=0; j<sizeof(file_buf); j++) {
FPGA_WAIT_RDY();
file_buf[j] = FPGA_RX_BYTE();
count++;
}
FPGA_DESELECT();
num = file_write();
if(file_res) {
uart_putc(0x30+file_res);
}
}
file_close();
}
uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size) {
uint8_t data;
uint32_t count;
uint32_t crc;
crc=0;
crc_valid=1;
set_mcu_addr(base_addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x88);
for(count=0; count<size; count++) {
FPGA_WAIT_RDY();
data = FPGA_RX_BYTE();
if(get_snes_reset()) {
crc_valid = 0;
break;
}
crc += crc32_update(crc, data);
}
FPGA_DESELECT();
return crc;
}
uint8_t sram_reliable() {
uint16_t score=0;
uint32_t val;
uint8_t result = 0;
/*while(score<SRAM_RELIABILITY_SCORE) {
if(sram_readlong(SRAM_SCRATCHPAD)==val) {
score++;
} else {
set_pwr_led(0);
score=0;
}
} */
for(uint16_t i = 0; i < SRAM_RELIABILITY_SCORE; i++) {
val=sram_readlong(SRAM_SCRATCHPAD);
if(val==0x12345678) {
score++;
} else {
printf("i=%d val=%08lX\n", i, val);
}
}
if(score<SRAM_RELIABILITY_SCORE) {
result = 0;
/* dprintf("score=%d\n", score); */
} else {
result = 1;
}
rdyled(result);
return result;
}
void sram_memset(uint32_t base_addr, uint32_t len, uint8_t val) {
set_mcu_addr(base_addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x98);
for(uint32_t i=0; i<len; i++) {
FPGA_TX_BYTE(val);
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
}
uint64_t sram_gettime(uint32_t base_addr) {
set_mcu_addr(base_addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x88);
uint8_t data;
uint64_t result = 0LL;
/* 1st nibble is the century - 10 (binary)
4th nibble is the month (binary)
all other fields are BCD */
for(int i=0; i<12; i++) {
FPGA_WAIT_RDY();
data = FPGA_RX_BYTE();
data &= 0xf;
switch(i) {
case 0:
result = (result << 4) | ((data / 10) + 1);
result = (result << 4) | (data % 10);
break;
case 3:
result = (result << 4) | ((data / 10));
result = (result << 4) | (data % 10);
break;
default:
result = (result << 4) | data;
}
}
FPGA_DESELECT();
return result & 0x00ffffffffffffffLL;
}
void load_dspx(const uint8_t *filename, uint8_t coretype) {
UINT bytes_read;
DWORD filesize;
uint16_t word_cnt;
uint8_t wordsize_cnt = 0;
uint16_t sector_remaining = 0;
uint16_t sector_cnt = 0;
uint16_t pgmsize = 0;
uint16_t datsize = 0;
uint32_t pgmdata = 0;
uint16_t datdata = 0;
if(coretype & FEAT_ST0010) {
datsize = 1536;
pgmsize = 2048;
} else if (coretype & FEAT_DSPX) {
datsize = 1024;
pgmsize = 2048;
} else if (coretype & FEAT_CX4) {
datsize = 0;
pgmsize = 1024; /* Cx4 data ROM */
} else {
printf("load_dspx: unknown core (%02x)!\n", coretype);
}
file_open((uint8_t*)filename, FA_READ);
filesize = file_handle.fsize;
if(file_res) {
printf("Could not read %s: error %d\n", filename, file_res);
return;
}
fpga_reset_dspx_addr();
for(word_cnt = 0; word_cnt < pgmsize;) {
if(!sector_remaining) {
bytes_read = file_read();
sector_remaining = bytes_read;
sector_cnt = 0;
}
pgmdata = (pgmdata << 8) | file_buf[sector_cnt];
sector_cnt++;
wordsize_cnt++;
sector_remaining--;
if(wordsize_cnt == 3){
wordsize_cnt = 0;
word_cnt++;
fpga_write_dspx_pgm(pgmdata);
}
}
wordsize_cnt = 0;
if(coretype & FEAT_ST0010) {
file_seek(0xc000);
sector_remaining = 0;
}
for(word_cnt = 0; word_cnt < datsize;) {
if(!sector_remaining) {
bytes_read = file_read();
sector_remaining = bytes_read;
sector_cnt = 0;
}
datdata = (datdata << 8) | file_buf[sector_cnt];
sector_cnt++;
wordsize_cnt++;
sector_remaining--;
if(wordsize_cnt == 2){
wordsize_cnt = 0;
word_cnt++;
fpga_write_dspx_dat(datdata);
}
}
fpga_reset_dspx_addr();
file_close();
}

71
src/tests/memory.h Normal file
View File

@@ -0,0 +1,71 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
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
memory.h: RAM operations
*/
#ifndef MEMORY_H
#define MEMORY_H
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "smc.h"
#define SRAM_ROM_ADDR (0x000000L)
#define SRAM_SAVE_ADDR (0xE00000L)
#define SRAM_MENU_ADDR (0xE00000L)
#define SRAM_DB_ADDR (0xE40000L)
#define SRAM_DIR_ADDR (0xE10000L)
#define SRAM_CMD_ADDR (0xFF1000L)
#define SRAM_PARAM_ADDR (0xFF1004L)
#define SRAM_STATUS_ADDR (0xFF1100L)
#define SRAM_MENU_SAVE_ADDR (0xFF0000L)
#define SRAM_SCRATCHPAD (0xFFFF00L)
#define SRAM_DIRID (0xFFFFF0L)
#define SRAM_RELIABILITY_SCORE (0x100)
#define LOADROM_WITH_SRAM (1)
#define LOADROM_WITH_RESET (2)
uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags);
uint32_t load_sram(uint8_t* filename, uint32_t base_addr);
uint32_t load_sram_offload(uint8_t* filename, uint32_t base_addr);
uint32_t load_sram_rle(uint8_t* filename, uint32_t base_addr);
void load_dspx(const uint8_t* filename, uint8_t st0010);
void sram_hexdump(uint32_t addr, uint32_t len);
uint8_t sram_readbyte(uint32_t addr);
uint16_t sram_readshort(uint32_t addr);
uint32_t sram_readlong(uint32_t addr);
void sram_writebyte(uint8_t val, uint32_t addr);
void sram_writeshort(uint16_t val, uint32_t addr);
void sram_writelong(uint32_t val, uint32_t addr);
void sram_readblock(void* buf, uint32_t addr, uint16_t size);
void sram_readlongblock(uint32_t* buf, uint32_t addr, uint16_t count);
void sram_writeblock(void* buf, uint32_t addr, uint16_t size);
void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr);
uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size);
uint8_t sram_reliable(void);
void sram_memset(uint32_t base_addr, uint32_t len, uint8_t val);
uint64_t sram_gettime(uint32_t base_addr);
#endif

256
src/tests/msu1.c Normal file
View File

@@ -0,0 +1,256 @@
#include <string.h>
#include "config.h"
#include "uart.h"
#include "ff.h"
#include "diskio.h"
#include "spi.h"
#include "fpga_spi.h"
#include "cli.h"
#include "fileops.h"
#include "msu1.h"
#include "snes.h"
#include "timer.h"
#include "smc.h"
FIL msufile;
extern snes_romprops_t romprops;
int msu1_check_reset(void) {
static tick_t rising_ticks;
static uint8_t resbutton=0, resbutton_prev=0;
resbutton = get_snes_reset();
if(resbutton && !resbutton_prev) { /* push */
rising_ticks = getticks();
} else if(resbutton && resbutton_prev) { /* hold */
if(getticks() > rising_ticks + 99) {
return 1;
}
}
resbutton_prev = resbutton;
return 0;
}
int msu1_check(uint8_t* filename) {
/* open MSU file */
strcpy((char*)file_buf, (char*)filename);
strcpy(strrchr((char*)file_buf, (int)'.'), ".msu");
printf("MSU datafile: %s\n", file_buf);
if(f_open(&msufile, (const TCHAR*)file_buf, FA_READ) != FR_OK) {
printf("MSU datafile not found\n");
return 0;
}
romprops.fpga_features |= FEAT_MSU1;
return 1;
}
int msu1_loop() {
/* it is assumed that the MSU file is already opened by calling msu1_check(). */
UINT bytes_read = 1024;
UINT bytes_read2 = 1;
FRESULT res;
set_dac_vol(0x00);
while(fpga_status() & 0x4000);
uint16_t fpga_status_prev = fpga_status();
uint16_t fpga_status_now = fpga_status();
uint16_t dac_addr = 0;
uint16_t msu_addr = 0;
uint8_t msu_repeat = 0;
uint16_t msu_track = 0;
uint32_t msu_offset = 0;
uint32_t msu_loop_point = 0;
uint32_t msu_page1_start = 0x0000;
uint32_t msu_page2_start = 0x2000;
uint32_t msu_page_size = 0x2000;
set_msu_addr(0x0);
msu_reset(0x0);
ff_sd_offload=1;
sd_offload_tgt=2;
f_lseek(&msufile, 0L);
ff_sd_offload=1;
sd_offload_tgt=2;
f_read(&msufile, file_buf, 16384, &bytes_read2);
set_dac_addr(dac_addr);
dac_pause();
dac_reset();
/* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */
while(1){
cli_entrycheck();
fpga_status_now = fpga_status();
/* Data buffer refill */
if((fpga_status_now & 0x2000) != (fpga_status_prev & 0x2000)) {
DBG_MSU1 printf("data\n");
uint8_t pageno = 0;
if(fpga_status_now & 0x2000) {
msu_addr = 0x0;
msu_page1_start = msu_page2_start + msu_page_size;
pageno = 1;
} else {
msu_addr = 0x2000;
msu_page2_start = msu_page1_start + msu_page_size;
pageno = 2;
}
set_msu_addr(msu_addr);
sd_offload_tgt=2;
ff_sd_offload=1;
res = f_read(&msufile, file_buf, 8192, &bytes_read2);
DBG_MSU1 printf("data buffer refilled. res=%d page1=%08lx page2=%08lx\n", res, msu_page1_start, msu_page2_start);
}
/* Audio buffer refill */
if((fpga_status_now & 0x4000) != (fpga_status_prev & 0x4000)) {
if(fpga_status_now & 0x4000) {
dac_addr = 0;
} else {
dac_addr = MSU_DAC_BUFSIZE/2;
}
set_dac_addr(dac_addr);
sd_offload_tgt=1;
ff_sd_offload=1;
f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE/2, &bytes_read);
}
if(fpga_status_now & 0x0020) {
char suffix[11];
/* get trackno */
msu_track = get_msu_track();
printf("Audio requested! Track=%d\n", msu_track);
/* open file, fill buffer */
f_close(&file_handle);
snprintf(suffix, sizeof(suffix), "-%d.pcm", msu_track);
strcpy((char*)file_buf, (char*)file_lfn);
strcpy(strrchr((char*)file_buf, (int)'.'), suffix);
printf("filename: %s\n", file_buf);
f_open(&file_handle, (const TCHAR*)file_buf, FA_READ);
f_lseek(&file_handle, 4L);
f_read(&file_handle, &msu_loop_point, 4, &bytes_read);
printf("loop point: %ld samples\n", msu_loop_point);
ff_sd_offload=1;
sd_offload_tgt=1;
f_lseek(&file_handle, 8L);
set_dac_addr(0);
dac_pause();
dac_reset();
ff_sd_offload=1;
sd_offload_tgt=1;
f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE, &bytes_read);
/* clear busy bit */
set_msu_status(0x00, 0x20); /* set no bits, reset bit 5 */
}
if(fpga_status_now & 0x0010) {
/* get address */
msu_offset=get_msu_offset();
printf("Data requested! Offset=%08lx page1=%08lx page2=%08lx\n", msu_offset, msu_page1_start, msu_page2_start);
if( ((msu_offset < msu_page1_start)
|| (msu_offset >= msu_page1_start + msu_page_size))
&& ((msu_offset < msu_page2_start)
|| (msu_offset >= msu_page2_start + msu_page_size))) {
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);
/* "cache miss" */
/* fill buffer */
set_msu_addr(0x0);
sd_offload_tgt=2;
ff_sd_offload=1;
res = f_lseek(&msufile, msu_offset);
DBG_MSU1 printf("seek to %08lx, res = %d\n", msu_offset, res);
sd_offload_tgt=2;
ff_sd_offload=1;
res = f_read(&msufile, file_buf, 16384, &bytes_read2);
DBG_MSU1 printf("read res = %d\n", res);
DBG_MSU1 printf("read %d bytes\n", bytes_read2);
msu_reset(0x0);
msu_page1_start = msu_offset;
msu_page2_start = msu_offset + 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);
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)) {
set_msu_addr(0x2000);
sd_offload_tgt=2;
ff_sd_offload=1;
f_read(&msufile, file_buf, 8192, &bytes_read2);
DBG_MSU1 printf("next page dirty (was: %08lx), loaded page2 (start now: ", msu_page2_start);
msu_page2_start = msu_page1_start + msu_page_size;
DBG_MSU1 printf("%08lx)\n", msu_page2_start);
}
} 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);
msu_reset(0x2000 + msu_offset - msu_page2_start);
if(!(msu_page1_start == msu_page2_start + msu_page_size)) {
set_msu_addr(0x0);
sd_offload_tgt=2;
ff_sd_offload=1;
f_read(&msufile, file_buf, 8192, &bytes_read2);
DBG_MSU1 printf("next page dirty (was: %08lx), loaded page1 (start now: ", msu_page1_start);
msu_page1_start = msu_page2_start + msu_page_size;
DBG_MSU1 printf("%08lx)\n", msu_page1_start);
}
} else printf("!!!WATWATWAT!!!\n");
}
/* clear bank bit to mask bank reset artifact */
fpga_status_now &= ~0x2000;
fpga_status_prev &= ~0x2000;
/* clear busy bit */
set_msu_status(0x00, 0x10);
}
if(fpga_status_now & 0x0001) {
if(fpga_status_now & 0x0004) {
msu_repeat = 1;
set_msu_status(0x04, 0x01); /* set bit 2, reset bit 0 */
printf("Repeat set!\n");
} else {
msu_repeat = 0;
set_msu_status(0x00, 0x05); /* set no bits, reset bit 0+2 */
printf("Repeat clear!\n");
}
if(fpga_status_now & 0x0002) {
printf("PLAY!\n");
set_msu_status(0x02, 0x01); /* set bit 0, reset bit 1 */
dac_play();
} else {
printf("PAUSE!\n");
set_msu_status(0x00, 0x03); /* set no bits, reset bit 1+0 */
dac_pause();
}
}
fpga_status_prev = fpga_status_now;
/* handle loop / end */
if(bytes_read < MSU_DAC_BUFSIZE / 2) {
ff_sd_offload=0;
sd_offload=0;
if(msu_repeat) {
printf("loop\n");
ff_sd_offload=1;
sd_offload_tgt=1;
f_lseek(&file_handle, 8L+msu_loop_point*4);
ff_sd_offload=1;
sd_offload_tgt=1;
f_read(&file_handle, file_buf, (MSU_DAC_BUFSIZE / 2) - bytes_read, &bytes_read);
} else {
set_msu_status(0x00, 0x02); /* clear play bit */
}
bytes_read = MSU_DAC_BUFSIZE;
}
if(msu1_check_reset()) {
f_close(&msufile);
f_close(&file_handle);
return 1;
}
}
}
/* END OF MSU1 STUFF */

15
src/tests/msu1.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef MSU1_H
#define MSU1_H
#ifdef DEBUG_MSU1
#define DBG_MSU1
#else
#define DBG_MSU1 while(0)
#endif
#define MSU_DAC_BUFSIZE (2048)
int msu1_check(uint8_t*);
int msu1_loop(void);
#endif

12
src/tests/openocd-usb.cfg Normal file
View File

@@ -0,0 +1,12 @@
#
# Hubert Hoegl's USB to JTAG
#
# http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html
#
interface ft2232
ft2232_vid_pid 0x0403 0x6010
ft2232_device_desc "Dual RS232"
ft2232_layout "oocdlink"
ft2232_latency 2
#adapter_khz 10

26
src/tests/power.c Normal file
View File

@@ -0,0 +1,26 @@
/* ___DISCLAIMER___ */
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "bits.h"
#include "power.h"
/*
required units:
* SSP0 (FPGA interface) [enabled via spi_init]
* UART3 (debug console) [enabled via uart_init]
* TIM3 (FPGA clock)
* RTC
* GPIO
* GPDMA [enabled via spi_init]
* USB [enabled via usb_init]
* PWM1
*/
void power_init() {
LPC_SC->PCONP = BV(PCSSP0)
| BV(PCTIM3)
| BV(PCRTC)
| BV(PCGPIO)
| BV(PCPWM1)
// | BV(PCUSB)
;
}

43
src/tests/power.h Normal file
View File

@@ -0,0 +1,43 @@
/* ___DISCLAIMER___ */
#ifndef _POWER_H
#define _POWER_H
#include "bits.h"
#define PCUART0 (3)
#define PCUART1 (4)
#define PCUART2 (24)
#define PCUART3 (25)
#define PCTIM0 (1)
#define PCTIM1 (2)
#define PCTIM2 (22)
#define PCTIM3 (23)
#define PCRTC (9)
#define PCRIT (16)
#define PCCAN1 (13)
#define PCCAN2 (14)
#define PCPWM1 (6)
#define PCMCPWM (17)
#define PCSSP0 (21)
#define PCSSP1 (10)
#define PCSPI (8)
#define PCI2C0 (7)
#define PCI2C1 (19)
#define PCI2C2 (26)
#define PCI2S (27)
#define PCGPDMA (29)
#define PCENET (30)
#define PCUSB (31)
#define PCQEI (18)
#define PCGPIO (15)
void power_init(void);
#endif

291
src/tests/printf.c Normal file
View File

@@ -0,0 +1,291 @@
/* Small, noncompliant, not-full-featured printf implementation
*
*
* Copyright (c) 2010, Ingo Korb
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Ingo Korb nor the
* names of the contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* FIXME: Selection of output function should be more flexible
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "config.h"
#include "uart.h"
#define outfunc(x) uart_putc(x)
#define FLAG_ZEROPAD 1
#define FLAG_LEFTADJ 2
#define FLAG_BLANK 4
#define FLAG_FORCESIGN 8
#define FLAG_WIDTH 16
#define FLAG_LONG 32
#define FLAG_UNSIGNED 64
#define FLAG_NEGATIVE 128
/* Digits used for conversion */
static const char hexdigits[] = "0123456789abcdef";
/* Temporary buffer used for numbers - just large enough for 32 bit in octal */
static char buffer[12];
/* Output string length */
static unsigned int outlength;
/* Output pointer */
static char *outptr;
static int maxlen;
/* printf */
static void outchar(char x) {
if (maxlen) {
maxlen--;
outfunc(x);
outlength++;
}
}
/* sprintf */
static void outstr(char x) {
if (maxlen) {
maxlen--;
*outptr++ = x;
outlength++;
}
}
static int internal_nprintf(void (*output_function)(char c), const char *fmt, va_list ap) {
unsigned int width;
unsigned int flags;
unsigned int base = 0;
char *ptr = NULL;
outlength = 0;
while (*fmt) {
while (1) {
if (*fmt == 0)
goto end;
if (*fmt == '%') {
fmt++;
if (*fmt != '%')
break;
}
output_function(*fmt++);
}
flags = 0;
width = 0;
/* read all flags */
do {
if (flags < FLAG_WIDTH) {
switch (*fmt) {
case '0':
flags |= FLAG_ZEROPAD;
continue;
case '-':
flags |= FLAG_LEFTADJ;
continue;
case ' ':
flags |= FLAG_BLANK;
continue;
case '+':
flags |= FLAG_FORCESIGN;
continue;
}
}
if (flags < FLAG_LONG) {
if (*fmt >= '0' && *fmt <= '9') {
unsigned char tmp = *fmt - '0';
width = 10*width + tmp;
flags |= FLAG_WIDTH;
continue;
}
if (*fmt == 'h')
continue;
if (*fmt == 'l') {
flags |= FLAG_LONG;
continue;
}
}
break;
} while (*fmt++);
/* Strings */
if (*fmt == 'c' || *fmt == 's') {
switch (*fmt) {
case 'c':
buffer[0] = va_arg(ap, int);
ptr = buffer;
break;
case 's':
ptr = va_arg(ap, char *);
break;
}
goto output;
}
/* Numbers */
switch (*fmt) {
case 'u':
flags |= FLAG_UNSIGNED;
case 'd':
base = 10;
break;
case 'o':
base = 8;
flags |= FLAG_UNSIGNED;
break;
case 'p': // pointer
output_function('0');
output_function('x');
width -= 2;
case 'x':
case 'X':
base = 16;
flags |= FLAG_UNSIGNED;
break;
}
unsigned int num;
if (!(flags & FLAG_UNSIGNED)) {
int tmp = va_arg(ap, int);
if (tmp < 0) {
num = -tmp;
flags |= FLAG_NEGATIVE;
} else
num = tmp;
} else {
num = va_arg(ap, unsigned int);
}
/* Convert number into buffer */
ptr = buffer + sizeof(buffer);
*--ptr = 0;
do {
*--ptr = hexdigits[num % base];
num /= base;
} while (num != 0);
/* Sign */
if (flags & FLAG_NEGATIVE) {
output_function('-');
width--;
} else if (flags & FLAG_FORCESIGN) {
output_function('+');
width--;
} else if (flags & FLAG_BLANK) {
output_function(' ');
width--;
}
output:
/* left padding */
if ((flags & FLAG_WIDTH) && !(flags & FLAG_LEFTADJ)) {
while (strlen(ptr) < width) {
if (flags & FLAG_ZEROPAD)
output_function('0');
else
output_function(' ');
width--;
}
}
/* data */
while (*ptr) {
output_function(*ptr++);
if (width)
width--;
}
/* right padding */
if (flags & FLAG_WIDTH) {
while (width) {
output_function(' ');
width--;
}
}
fmt++;
}
end:
return outlength;
}
int printf(const char *format, ...) {
va_list ap;
int res;
maxlen = -1;
va_start(ap, format);
res = internal_nprintf(outchar, format, ap);
va_end(ap);
return res;
}
int snprintf(char *str, size_t size, const char *format, ...) {
va_list ap;
int res;
maxlen = size;
outptr = str;
va_start(ap, format);
res = internal_nprintf(outstr, format, ap);
va_end(ap);
if (res < size)
str[res] = 0;
return res;
}
/* Required for gcc compatibility */
int puts(const char *str) {
uart_puts(str);
uart_putc('\n');
return 0;
}
#undef putchar
int putchar(int c) {
uart_putc(c);
return 0;
}

3
src/tests/reset.cfg Normal file
View File

@@ -0,0 +1,3 @@
init
reset run
shutdown

66
src/tests/rle.c Normal file
View File

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

17
src/tests/rle.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef RLE_H
#define RLE_H
#include <arm/NXP/LPC17xx/LPC17xx.h>
#define RLE_ESC (0x9b)
#define RLE_RUN (0x5b)
#define RLE_RUNLONG (0x77)
uint8_t rle_file_getc(void);
uint8_t rle_mem_getc(void);
void rle_mem_init(const uint8_t *address, uint32_t len);
const uint8_t *rle_mem_ptr;
const uint8_t *rle_mem_endptr;
uint8_t rle_state;
#endif

135
src/tests/rtc.c Normal file
View File

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

78
src/tests/rtc.h Normal file
View File

@@ -0,0 +1,78 @@
/* 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
rtc.h: Definitions for RTC support
*/
#ifndef RTC_H
#define RTC_H
#include <stdint.h>
typedef enum {
RTC_NOT_FOUND, /* No RTC present */
RTC_INVALID, /* RTC present, but contents invalid */
RTC_OK /* RTC present and working */
} rtcstate_t;
struct tm {
uint8_t tm_sec; // 0..59
uint8_t tm_min; // 0..59
uint8_t tm_hour; // 0..23
uint8_t tm_mday; // 1..[28..31]
uint8_t tm_mon; // 0..11
uint16_t tm_year; // since 0 A.D.
uint8_t tm_wday; // 0 to 6, sunday is 6
// A Unix struct tm has a few more fields we don't need in this application
};
#define RTC_MAGIC (0x43545253L)
extern rtcstate_t rtc_state;
void rtc_init(void);
/* return RTC valid state based on magic token in backup register */
uint8_t rtc_isvalid(void);
/* Return current time in struct tm */
void read_rtc(struct tm *time);
/* Set time from struct tm, also sets RTC valid */
void set_rtc(struct tm *time);
/* Set RTC invalid */
void invalidate_rtc(void);
/* get current time in 60-bit BCD format (WYYYYMMDDHHMMSS) (W=DOW) */
uint64_t get_bcdtime(void);
/* set current time from 56-bit BCD format (YYYYMMDDHHMMSS)
DOW is calculated */
void set_bcdtime(uint64_t btime);
/* print the time to the console */
void printtime(struct tm *time);
void testbattery(void);
#endif

46
src/tests/sdcard.h Normal file
View File

@@ -0,0 +1,46 @@
/* 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

1015
src/tests/sdnative.c Normal file

File diff suppressed because it is too large Load Diff

29
src/tests/sdnative.h Normal file
View File

@@ -0,0 +1,29 @@
/* DISCLAIMER */
#ifndef SDNATIVE_H
#define SDNATIVE_H
#ifdef DEBUG_SD
#define DBG_SD
#else
#define DBG_SD while(0)
#endif
#include "diskio.h"
#define CRC_ERROR (0xf000)
extern int sd_offload;
/* These functions are weak-aliased to disk_... */
void sdn_init(void);
DSTATUS sdn_status(BYTE drv);
DSTATUS sdn_initialize(BYTE drv);
DRESULT sdn_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count);
DRESULT sdn_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count);
DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer);
void sdn_changed(void);
#endif

252
src/tests/smc.c Normal file
View File

@@ -0,0 +1,252 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
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
smc.c: SMC file related operations
*/
#include "fileops.h"
#include "config.h"
#include "uart.h"
#include "smc.h"
#include "string.h"
#include "fpga_spi.h"
snes_romprops_t romprops;
uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0};
uint8_t countAllASCII(uint8_t* data, int size) {
uint8_t res = 0;
do {
size--;
if(data[size] >= 0x20 && data[size] <= 0x7e) {
res++;
}
} while (size);
return res;
}
uint8_t countAllJISX0201(uint8_t* data, int size) {
uint8_t res = 0;
do {
size--;
if((data[size] >= 0x20 && data[size] <= 0x7e)
||(data[size] >= 0xa1 && data[size] <= 0xdf)) {
res++;
}
} while (size);
return res;
}
uint8_t isFixed(uint8_t* data, int size, uint8_t value) {
uint8_t res = 1;
do {
size--;
if(data[size] != value) {
res = 0;
}
} while (size);
return res;
}
uint8_t checkChksum(uint16_t cchk, uint16_t chk) {
uint32_t sum = cchk + chk;
uint8_t res = 0;
if(sum==0x0000ffff) {
res = 0x10;
}
return res;
}
void smc_id(snes_romprops_t* props) {
uint8_t score, maxscore=1, score_idx=2; /* assume LoROM */
snes_header_t* header = &(props->header);
props->has_dspx = 0;
props->has_st0010 = 0;
props->has_cx4 = 0;
props->fpga_features = 0;
props->fpga_conf = NULL;
for(uint8_t num = 0; num < 6; num++) {
if(!file_readblock(header, hdr_addr[num], sizeof(snes_header_t))
|| file_res) {
score = 0;
} else {
score = smc_headerscore(header)/(1+(num&1));
if((file_handle.fsize & 0x2ff) == 0x200) {
if(num&1) {
score+=20;
} else {
score=0;
}
} else {
if(!(num&1)) {
score+=20;
} else {
score=0;
}
}
}
//printf("%d: offset = %lX; score = %d\n", num, hdr_addr[num], score); // */
if(score>=maxscore) {
score_idx=num;
maxscore=score;
}
}
if(score_idx & 1) {
props->offset = 0x200;
} else {
props->offset = 0;
}
/* restore the chosen one */
/*dprintf("winner is %d\n", score_idx); */
file_readblock(header, hdr_addr[score_idx], sizeof(snes_header_t));
if(header->name[0x13] == 0x00 || header->name[0x13] == 0xff) {
if(header->name[0x14] == 0x00) {
const uint8_t n15 = header->map;
if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c
|| n15 == 0xbc || n15 == 0xfc) {
if(header->licensee == 0x33 || header->licensee == 0xff) {
props->mapper_id = 0;
/*XXX do this properly */
props->ramsize_bytes = 0x8000;
props->romsize_bytes = 0x100000;
props->expramsize_bytes = 0;
props->mapper_id = 3; /* BS-X Memory Map */
return;
}
}
}
}
switch(header->map & 0xef) {
case 0x21: /* HiROM */
props->mapper_id = 0;
if(header->map == 0x31 && (header->carttype == 0x03 || header->carttype == 0x05)) {
props->has_dspx = 1;
props->dsp_fw = DSPFW_1B;
props->fpga_features |= FEAT_DSPX;
}
break;
case 0x20: /* LoROM */
props->mapper_id = 1;
if (header->map == 0x20 && header->carttype == 0xf3) {
props->has_cx4 = 1;
props->dsp_fw = CX4FW;
props->fpga_conf = FPGA_CX4;
props->fpga_features |= FEAT_CX4;
}
else if ((header->map == 0x20 && header->carttype == 0x03) ||
(header->map == 0x30 && header->carttype == 0x05 && header->licensee != 0xb2)) {
props->has_dspx = 1;
props->fpga_features |= FEAT_DSPX;
// Pilotwings uses DSP1 instead of DSP1B
if(!memcmp(header->name, "PILOTWINGS", 10)) {
props->dsp_fw = DSPFW_1;
} else {
props->dsp_fw = DSPFW_1B;
}
} else if (header->map == 0x20 && header->carttype == 0x05) {
props->has_dspx = 1;
props->dsp_fw = DSPFW_2;
props->fpga_features |= FEAT_DSPX;
} else if (header->map == 0x30 && header->carttype == 0x05 && header->licensee == 0xb2) {
props->has_dspx = 1;
props->dsp_fw = DSPFW_3;
props->fpga_features |= FEAT_DSPX;
} else if (header->map == 0x30 && header->carttype == 0x03) {
props->has_dspx = 1;
props->dsp_fw = DSPFW_4;
props->fpga_features |= FEAT_DSPX;
} else if (header->map == 0x30 && header->carttype == 0xf6 && header->romsize >= 0xa) {
props->has_dspx = 1;
props->has_st0010 = 1;
props->dsp_fw = DSPFW_ST0010;
props->fpga_features |= FEAT_ST0010;
header->ramsize = 2;
}
break;
case 0x25: /* ExHiROM */
props->mapper_id = 2;
break;
case 0x22: /* ExLoROM */
if(file_handle.fsize > 0x400200) {
props->mapper_id = 6; /* SO96 */
} else {
props->mapper_id = 1;
}
break;
default: /* invalid/unsupported mapper, use header location */
switch(score_idx) {
case 0:
case 1:
props->mapper_id = 0;
break;
case 2:
case 3:
if(file_handle.fsize > 0x800200) {
props->mapper_id = 6; /* SO96 interleaved */
} else if(file_handle.fsize > 0x400200) {
props->mapper_id = 1; /* ExLoROM */
} else {
props->mapper_id = 1; /* LoROM */
}
break;
case 4:
case 5:
props->mapper_id = 2;
break;
default:
props->mapper_id = 1; // whatever
}
}
if(header->romsize == 0 || header->romsize > 13) {
header->romsize = 13;
}
props->ramsize_bytes = (uint32_t)1024 << header->ramsize;
props->romsize_bytes = (uint32_t)1024 << header->romsize;
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) {
props->ramsize_bytes = 0;
}
/*dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); */
}
uint8_t smc_headerscore(snes_header_t* header) {
uint8_t score=0;
score += countAllASCII(header->maker, sizeof(header->maker));
score += countAllASCII(header->gamecode, sizeof(header->gamecode));
score += isFixed(header->fixed_00, sizeof(header->fixed_00), 0x00);
score += countAllJISX0201(header->name, sizeof(header->name));
score += 3*isFixed(&header->licensee, sizeof(header->licensee), 0x33);
score += checkChksum(header->cchk, header->chk);
return score;
}

79
src/tests/smc.h Normal file
View File

@@ -0,0 +1,79 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
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
smc.h: SMC file structures
*/
#ifndef SMC_H
#define SMC_H
#define DSPFW_1 ((const uint8_t*)"/sd2snes/dsp1.bin")
#define DSPFW_2 ((const uint8_t*)"/sd2snes/dsp2.bin")
#define DSPFW_3 ((const uint8_t*)"/sd2snes/dsp3.bin")
#define DSPFW_4 ((const uint8_t*)"/sd2snes/dsp4.bin")
#define DSPFW_1B ((const uint8_t*)"/sd2snes/dsp1b.bin")
#define DSPFW_ST0010 ((const uint8_t*)"/sd2snes/st0010.bin")
#define CX4FW ((const uint8_t*)"/sd2snes/cx4.bin")
#define FPGA_CX4 ((const uint8_t*)"/sd2snes/fpga_cx4.bit")
typedef struct _snes_header {
uint8_t maker[2]; /* 0xB0 */
uint8_t gamecode[4]; /* 0xB2 */
uint8_t fixed_00[7]; /* 0xB6 */
uint8_t expramsize; /* 0xBD */
uint8_t specver; /* 0xBE */
uint8_t carttype2; /* 0xBF */
uint8_t name[21]; /* 0xC0 */
uint8_t map; /* 0xD5 */
uint8_t carttype; /* 0xD6 */
uint8_t romsize; /* 0xD7 */
uint8_t ramsize; /* 0xD8 */
uint8_t destcode; /* 0xD9 */
uint8_t licensee; /* 0xDA */
uint8_t ver; /* 0xDB */
uint16_t cchk; /* 0xDC */
uint16_t chk; /* 0xDE */
} snes_header_t;
typedef struct _snes_romprops {
uint16_t offset; /* start of actual ROM image */
uint8_t mapper_id; /* FPGA mapper */
uint8_t pad1; /* for alignment */
uint32_t expramsize_bytes; /* ExpRAM size in bytes */
uint32_t ramsize_bytes; /* CartRAM size in bytes */
uint32_t romsize_bytes; /* ROM size in bytes (rounded up) */
const uint8_t* dsp_fw; /* DSP (NEC / Hitachi) ROM filename */
const uint8_t* fpga_conf; /* FPGA config file to load (default: base) */
uint8_t has_dspx; /* DSP[1-4] presence flag */
uint8_t has_st0010; /* st0010 presence flag (additional to dspx)*/
uint8_t has_msu1; /* MSU1 presence flag */
uint8_t has_cx4; /* CX4 presence flag */
uint8_t fpga_features; /* feature/peripheral enable bits*/
snes_header_t header; /* original header from ROM image */
} snes_romprops_t;
void smc_id(snes_romprops_t*);
uint8_t smc_headerscore(snes_header_t*);
#endif

174
src/tests/snes.c Normal file
View File

@@ -0,0 +1,174 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
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
snes.c: SNES hardware control and monitoring
*/
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "bits.h"
#include "config.h"
#include "uart.h"
#include "snes.h"
#include "memory.h"
#include "fileops.h"
#include "ff.h"
#include "led.h"
#include "smc.h"
#include "timer.h"
#include "cli.h"
#include "fpga.h"
#include "fpga_spi.h"
uint8_t initloop=1;
uint32_t saveram_crc, saveram_crc_old;
extern snes_romprops_t romprops;
volatile int reset_changed;
void prepare_reset() {
snes_reset(1);
delay_ms(1);
if(romprops.ramsize_bytes && fpga_test() == FPGA_TEST_TOKEN) {
writeled(1);
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
writeled(0);
}
rdyled(1);
readled(1);
writeled(1);
snes_reset(0);
while(get_snes_reset());
snes_reset(1);
fpga_dspx_reset(1);
delay_ms(200);
}
void snes_init() {
/* put reset level on reset pin */
BITBAND(SNES_RESET_REG->FIOCLR, SNES_RESET_BIT) = 1;
/* reset the SNES */
snes_reset(1);
}
/*
* sets the SNES reset state.
*
* state: put SNES in reset state when 1, release when 0
*/
void snes_reset(int state) {
BITBAND(SNES_RESET_REG->FIODIR, SNES_RESET_BIT) = state;
}
/*
* gets the SNES reset state.
*
* returns: 1 when reset, 0 when not reset
*/
uint8_t get_snes_reset() {
return !BITBAND(SNES_RESET_REG->FIOPIN, SNES_RESET_BIT);
}
/*
* SD2SNES main loop.
* monitors SRAM changes and other things
*/
uint32_t diffcount = 0, samecount = 0, didnotsave = 0;
uint8_t sram_valid = 0;
void snes_main_loop() {
if(!romprops.ramsize_bytes)return;
if(initloop) {
saveram_crc_old = calc_sram_crc(SRAM_SAVE_ADDR, romprops.ramsize_bytes);
initloop=0;
}
saveram_crc = calc_sram_crc(SRAM_SAVE_ADDR, romprops.ramsize_bytes);
sram_valid = sram_reliable();
if(crc_valid && sram_valid) {
if(saveram_crc != saveram_crc_old) {
if(samecount) {
diffcount=1;
} else {
diffcount++;
didnotsave++;
}
samecount=0;
}
if(saveram_crc == saveram_crc_old) {
samecount++;
}
if(diffcount>=1 && samecount==5) {
printf("SaveRAM CRC: 0x%04lx; saving\n", saveram_crc);
writeled(1);
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
writeled(0);
didnotsave=0;
}
if(didnotsave>50) {
printf("periodic save (sram contents keep changing...)\n");
diffcount=0;
writeled(1);
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
didnotsave=0;
writeled(0);
}
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);
}
/*
* SD2SNES menu loop.
* monitors menu selection. return when selection was made.
*/
uint8_t menu_main_loop() {
uint8_t cmd = 0;
sram_writebyte(0, SRAM_CMD_ADDR);
while(!cmd) {
if(!get_snes_reset()) {
while(!sram_reliable())printf("hurr\n");
cmd = sram_readbyte(SRAM_CMD_ADDR);
}
if(get_snes_reset()) {
cmd = 0;
}
sleep_ms(20);
cli_entrycheck();
}
return cmd;
}
void get_selected_name(uint8_t* fn) {
uint32_t addr;
addr = sram_readlong(SRAM_PARAM_ADDR);
printf("fd addr=%lx\n", addr);
sram_readblock(fn, addr + 7 + SRAM_MENU_ADDR, 256);
}
void snes_bootprint(void* msg) {
sram_writeblock(msg, SRAM_CMD_ADDR, 33);
}
void snes_menu_errmsg(int err, void* msg) {
sram_writeblock(msg, SRAM_CMD_ADDR+1, 64);
sram_writebyte(err, SRAM_CMD_ADDR);
}

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