127 Commits

Author SHA1 Message Date
Godzil
0ea53495b0 Merge branch 'develop' into merging
Conflicts:
	src/bootldr/fileops.h
	src/bootldr/iap.c
	src/fpga_spi.c
	src/memory.c
	src/smc.c
	verilog/sd2snes/address.v
2014-01-16 22:16:51 +00:00
Maximilian Rehkopf
3cc8af1753 Menu: rename menu labels to "filesel", minor tweaks/fixes 2013-10-18 15:35:41 +02:00
Maximilian Rehkopf
c8b24a9618 Firmware: fix loading of partial-size BS dumps 2013-10-18 15:32:42 +02:00
Maximilian Rehkopf
c380ce9503 Adjust OpenOCD configuration for more recent versions 2013-10-18 15:31:25 +02:00
Maximilian Rehkopf
a734ae1ec5 pamper the compiler 2013-10-18 15:30:08 +02:00
Maximilian Rehkopf
f7d393451a Firmware: timeouts for FPGA configuration; LED flash codes for various FPGA related errors 2013-10-18 14:43:02 +02:00
Maximilian Rehkopf
28949ac307 Firmware: preparations for USB 2013-10-18 14:40:20 +02:00
Maximilian Rehkopf
4ff823078f Bootloader: fix flash buffer alignment 2013-10-18 14:37:36 +02:00
Maximilian Rehkopf
988d84954b Bootloader: change baud rate from 921600 to more common 115200 2013-10-18 14:37:12 +02:00
Maximilian Rehkopf
3f2e4e37db menu: rename menu.a65 to filesel.a65; add required library to README 2013-10-18 14:20:19 +02:00
Godzil
1d928e7091 Merge branch 'udev' into develop 2013-10-06 14:52:40 +01:00
Maximilian Rehkopf
39b07df47e Correct LoROM SRAM mapping for smaller ROMs
SRAM is sometimes mapped not just to 70:0000-7fff but also to
70:8000-ffff if ROM size permits it (i.e. the ROM is small enough
to avoid overlap).
Map SRAM to 8000-ffff if the ROM mask denotes a ROM <= 16 MBits.
2013-06-30 23:42:28 +02:00
Maximilian Rehkopf
78beed80d7 FPGA: fix BSX PSRAM mapping 2013-06-26 10:44:57 +02:00
Maximilian Rehkopf
f7aa9832c6 update changelog 2012-11-18 21:01:39 +01:00
Maximilian Rehkopf
7233278db2 Firmware: fix FPGA DMA call 2012-11-18 20:12:19 +01:00
Maximilian Rehkopf
443f7b138c Firmware: update version number to 0.1.5 2012-11-18 20:11:46 +01:00
Maximilian Rehkopf
e92ad06f38 FPGA/Cx4: slow down bus timing 2012-11-18 20:10:29 +01:00
Maximilian Rehkopf
fa1e09d867 FPGA: fix large SRAM mapping 2012-11-18 17:18:26 +01:00
Maximilian Rehkopf
e504079e5d FPGA: slow down bus timing 2012-11-07 22:32:33 +01:00
Maximilian Rehkopf
1f5af01bc0 FPGA: add BS-X "hole" (regs 09-0b) 2012-11-07 22:31:28 +01:00
Maximilian Rehkopf
648569d900 Firmware: fix big SRAM handling 2012-11-07 22:29:38 +01:00
Maximilian Rehkopf
b91b598758 Firmware: fix MSU1 main loop behaviour 2012-11-07 11:06:56 +01:00
Maximilian Rehkopf
04c3cbc7a2 Firmware: [debug] log file size after loading 2012-11-07 11:06:29 +01:00
Maximilian Rehkopf
c204aa9a0b Firmware/FPGA: replace magic numbers with constants 2012-11-07 11:03:58 +01:00
Maximilian Rehkopf
605fc2dfb1 Firmware: remove unused file sdcard.h 2012-11-07 09:54:30 +01:00
Maximilian Rehkopf
b67e2a5c77 Firmware: clean up clock/timer init 2012-11-07 09:44:50 +01:00
Maximilian Rehkopf
fee97e5016 Firmware/CLI: list short file name and file size in ls command; print file name when saving SRAM 2012-11-07 09:31:33 +01:00
Maximilian Rehkopf
ce23ff6954 Firmware/CLI: add memset command, rename 'resume' to 'exit' 2012-11-07 09:27:00 +01:00
Maximilian Rehkopf
83b18cc447 Firmware: fix compile errors with newer gccs 2012-11-07 09:23:50 +01:00
Maximilian Rehkopf
e33fbdf77f menu: Ignore input from non-standard controllers (resolve #29) 2012-09-30 00:24:48 +02:00
Maximilian Rehkopf
9287d637d1 FPGA: properly map large SRAM (LoROM > 32kB, HiROM > 8kB) 2012-09-24 22:52:05 +02:00
Maximilian Rehkopf
13c24bea9d FPGA: more accurate BS-X memory map 2012-09-24 22:49:54 +02:00
Maximilian Rehkopf
791b688f40 menu: fix #26: first note cut off on S-APU SNESes 2012-09-24 22:37:39 +02:00
Maximilian Rehkopf
5939b6e581 Firmware: sort by entire filename, not just first 20 characters 2012-08-25 19:36:24 +02:00
Godzil
043eeea399 Automate cfgware.h file generation. Will automatically search the .bit file from sd2sneslite rle it and convert to .h file. 2012-08-23 16:55:50 +02:00
Godzil
c4ef438cac Update openocd interface to match my own interface 2012-08-17 18:32:00 +02:00
Maximilian Rehkopf
82998d7a48 PCB/Rev.E2: Add BOM 2012-08-06 23:33:01 +02:00
Maximilian Rehkopf
32a0a50c54 update changelog for 0.1.4a 2012-07-15 20:21:14 +02:00
Maximilian Rehkopf
b8d3b952ad firmware: bump version no. to 0.1.4a 2012-07-14 21:27:07 +02:00
Maximilian Rehkopf
e97396adc9 menu: fix DMA initialization (sprite glitches in some games) 2012-07-14 21:25:51 +02:00
mrehkopf
a72476ea6c Merge pull request #24 from Godzil/develop
Develop
2012-07-10 03:53:32 -07:00
Maximilian Rehkopf
d47858083a FPGA/Cx4: update user constraints for changed system clock 2012-07-09 18:52:51 +02:00
Maximilian Rehkopf
a7ac2f8900 update changelog 2012-07-09 18:52:03 +02:00
Maximilian Rehkopf
c80bdfbf59 Firmware: do not turn off write LED in case of periodic SRAM saving 2012-07-09 02:28:26 +02:00
Maximilian Rehkopf
a9ea821c0d Firmware: implement MSU1 interface changes 2012-07-09 02:27:53 +02:00
Maximilian Rehkopf
9baa4b7f9f Firmware: move SaveRAM to $E00000 2012-07-09 02:26:50 +02:00
Maximilian Rehkopf
2ef480f751 FPGA/DSPx: buffer register input 2012-07-09 02:23:57 +02:00
Maximilian Rehkopf
6b3a7eb4ae FPGA/SRTC: buffer register/address input 2012-07-09 02:22:57 +02:00
Maximilian Rehkopf
effa2a6972 FPGA/SDDMA: fix clock glitch, adjust RAM write timings 2012-07-09 02:22:07 +02:00
Maximilian Rehkopf
9253cc45b0 FPGA: implement MSU1 "audio error" status bit 2012-07-09 02:20:13 +02:00
Maximilian Rehkopf
9fbe61bad1 FPGA: Use internal clock instead of SNES master clock for $213F RMW timing 2012-07-09 02:18:28 +02:00
Maximilian Rehkopf
968c347986 FPGA/SPI: detect end of byte via MSB toggle instead of constant compare of async input 2012-07-09 02:17:01 +02:00
Maximilian Rehkopf
c231c8b821 FPGA: misc cleanup 2012-07-09 02:15:21 +02:00
Maximilian Rehkopf
60d7a08117 FPGA: Adjust Cx4 timing to new master clock rate 2012-07-09 02:13:44 +02:00
Maximilian Rehkopf
7df6909266 FPGA: rework shared memory access FSM 2012-07-09 02:12:59 +02:00
Maximilian Rehkopf
006ea8c44a FPGA: debug wires 2012-07-09 02:03:59 +02:00
Maximilian Rehkopf
684e2c3b81 FPGA/BSX: fix checksum registers 2012-07-09 02:00:29 +02:00
Maximilian Rehkopf
3af05cef91 FPGA/sd2sneslite: add missing file mcu_cmd.v; remove avr_cmd.v 2012-07-09 01:55:02 +02:00
Maximilian Rehkopf
a083d80ff9 FPGA: update clock speed to 88MHz 2012-07-09 01:54:05 +02:00
Maximilian Rehkopf
8148f5567c FPGA: properly synchronize external signals 2012-07-09 01:48:43 +02:00
Maximilian Rehkopf
1a52da6272 FPGA: Adjust DAC I²S signal timing 2012-07-09 01:41:47 +02:00
Maximilian Rehkopf
e33b2b2bc7 FPGA: simple SNES address input filtering 2012-07-09 01:37:57 +02:00
Maximilian Rehkopf
3530613349 FPGA: prepare new SNES command interface for future use (SNES side) 2012-07-09 01:29:47 +02:00
Maximilian Rehkopf
0d02bfded7 Firmware: adjust to SPI changes 2012-07-09 01:19:44 +02:00
Maximilian Rehkopf
576cedd285 Update embedded FPGA config 2012-07-09 01:17:32 +02:00
Maximilian Rehkopf
e6f77c242b Update changelog for version 0.1.4 2012-07-09 01:16:39 +02:00
Godzil
86d6f04870 Add gitignore file. 2012-07-05 14:42:02 +02:00
Godzil
e2af175f05 Correct baudrate on normal application. 2012-07-05 14:41:29 +02:00
Godzil
583309491c Change baudrate to more standard 115200 2012-07-05 14:41:06 +02:00
Maximilian Rehkopf
40099772f7 menu: comments 2012-07-03 20:44:17 +02:00
Maximilian Rehkopf
247e6591c4 menu: replace AVR with MCU in labels 2012-07-03 20:43:48 +02:00
Maximilian Rehkopf
1b77a6e7fa menu: remove redundant code from DMA macro 2012-07-03 20:43:18 +02:00
Maximilian Rehkopf
eede8b491b menu: properly init P register for gettimt 2012-07-03 16:21:46 +02:00
Maximilian Rehkopf
350b83e06b menu: fix scroll bug when entering directories with long names 2012-07-03 16:20:45 +02:00
Maximilian Rehkopf
943a3d14bb menu: fix order of SNES initialization 2012-07-03 16:18:12 +02:00
Maximilian Rehkopf
5eae77f626 menu: fade in screen on cold boot 2012-07-03 16:14:39 +02:00
Maximilian Rehkopf
14a2136be7 menu: speed up print routine, move tilemap buffers to bank $7E 2012-07-03 16:10:30 +02:00
Maximilian Rehkopf
45b67d0f1a Firmware: Change ROM size detection for broken headers 2012-07-01 03:27:34 +02:00
Maximilian Rehkopf
e23a76d812 Firmware: properly enable offloading before f_lseek 2012-07-01 03:25:37 +02:00
Maximilian Rehkopf
f4b8d57810 Firmware/FatFs: make f_gets break on NUL character as well 2012-07-01 03:24:35 +02:00
Maximilian Rehkopf
1be6885223 Firmware: bump default date 2012-07-01 03:23:27 +02:00
Maximilian Rehkopf
2eeaaefcef Firmware/SD: implement FatFs CTRL_SYNC ioctl (issue #4) 2012-07-01 03:20:27 +02:00
Maximilian Rehkopf
71aef898d2 Firmware: load database using DMA 2012-07-01 03:18:16 +02:00
Maximilian Rehkopf
d9e1680800 Firmware: remove SPI speed switching 2012-07-01 03:15:27 +02:00
Maximilian Rehkopf
57bb6351e7 Firmware: change CPU frequency to 88MHz 2012-07-01 03:12:05 +02:00
Maximilian Rehkopf
023901cab2 Firmware: refactor SNES reset pulse 2012-07-01 03:08:36 +02:00
Maximilian Rehkopf
6038d94d0f Firmware/cli: add mkdir command 2012-07-01 03:03:30 +02:00
Maximilian Rehkopf
aef19a2576 Firmware/cli: check parameters to saveraw command 2012-07-01 03:01:02 +02:00
Maximilian Rehkopf
3db272662c firmware: disregard trailing slash when sorting directory names 2012-06-11 02:00:58 +02:00
Maximilian Rehkopf
91458011aa minor comment cleanup 2012-06-11 02:00:18 +02:00
Maximilian Rehkopf
c062800386 firmware: speedup filesystem footprinting 2012-06-11 01:59:39 +02:00
Maximilian Rehkopf
61c7014f85 firmware: keep directory tables within bank boundaries 2012-06-11 01:59:04 +02:00
Maximilian Rehkopf
64b1b07333 firmware: change filesystem footprint calculation (order of files doesn't matter) 2012-06-11 01:57:06 +02:00
Maximilian Rehkopf
723bf9eb95 firmware: limit number of files per directory 2012-06-11 01:56:09 +02:00
Maximilian Rehkopf
9c84f01fd5 firmware: update embedded FPGA config 2012-06-11 01:54:48 +02:00
Maximilian Rehkopf
a5a02992e5 FPGA/embedded config: slightly tighten timing constraints 2012-06-11 01:52:45 +02:00
Maximilian Rehkopf
0f38935981 menu: fix xscroll bug when entering directories with scrolled names 2012-06-11 01:52:01 +02:00
Maximilian Rehkopf
f44de5ba64 menu/SPC player: fix "Artist" display for "binary format" ID666 tags 2012-06-11 01:50:35 +02:00
Maximilian Rehkopf
12deb9a0c7 firmware: correct number of files/dirs in system information 2012-06-10 20:28:33 +02:00
Maximilian Rehkopf
a1ca5f1dad firmware/SPC: zero echo buffer to avoid artifacts 2012-06-10 20:09:02 +02:00
Maximilian Rehkopf
ae4af50dac firmware: adjust SNES reset pulse 2012-06-10 20:08:31 +02:00
Maximilian Rehkopf
034b39588c FPGA: adjust menu memory mapping to make more room for file database 2012-06-10 20:07:45 +02:00
Maximilian Rehkopf
66f26c18b1 menu: make room for larger file database (adjust addresses) 2012-06-10 20:05:58 +02:00
Maximilian Rehkopf
96e178df2e firmware: make room for larger file database 2012-06-10 20:04:48 +02:00
Maximilian Rehkopf
f28516ea1c firmware: fix sort order (force parent dir at top of list) 2012-06-09 21:55:08 +02:00
Maximilian Rehkopf
242bde5684 firmware: file size adaptive ROM mirroring 2012-06-09 21:52:24 +02:00
Maximilian Rehkopf
8c2f74d8cd firmware: SPC player (necronomfive) 2012-06-09 21:51:15 +02:00
Maximilian Rehkopf
11bf7ffd5b firmware: case-insensitive system directory hiding 2012-06-09 21:50:34 +02:00
Maximilian Rehkopf
b01388b670 firmware: bump version number to 0.1.4 2012-06-09 21:48:53 +02:00
Maximilian Rehkopf
1f9dbe7d4c menu: fix occasional palette corruption (necronomfive) 2012-06-09 21:48:09 +02:00
Maximilian Rehkopf
798e23ec82 menu: show CPU/PPU revisions in system information (necronomfive) 2012-06-09 21:47:40 +02:00
Maximilian Rehkopf
f9c8e62f10 menu: SPC player (necronomfive, blargg) 2012-06-09 21:25:45 +02:00
Maximilian Rehkopf
c07b8f42c2 firmware/test suite: add missing file tests.c 2012-06-09 02:12:48 +02:00
Maximilian Rehkopf
2a1ef40796 FPGA/cx4: adjust Cx4 CPU timing 2012-05-19 18:07:13 +02:00
Maximilian Rehkopf
873bd84cd1 Firmware: set BS region override correctly 2012-05-02 12:13:58 +02:00
Maximilian Rehkopf
36dece67b8 Firmware: add basic BS download page file 2012-05-02 12:12:50 +02:00
Maximilian Rehkopf
de4308e3ba Firmware/BS: load BS download page file 2012-05-02 11:01:07 +02:00
Maximilian Rehkopf
6cff0f66e0 Firmware: auto-detect version number base in firmware image generator 2012-05-02 10:57:19 +02:00
Maximilian Rehkopf
dc478186e5 Firmware: add words of wisdom in README after switching from Ubuntu to Fedora Core ;-) 2012-05-02 10:51:18 +02:00
Maximilian Rehkopf
7109f9e030 FPGA: add SD clock pullup to test configuration 2012-05-02 10:46:27 +02:00
Maximilian Rehkopf
e63658e2ad FPGA: Map mode 21 SRAM to 20:xxxx as well 2012-05-02 10:46:01 +02:00
Maximilian Rehkopf
37a309fd0e FPGA: improve BS support (more date fields, initial download data support) 2012-05-02 10:42:46 +02:00
Maximilian Rehkopf
f5caf21fac FPGA: slightly tighten timing constraints 2012-05-02 10:41:07 +02:00
Maximilian Rehkopf
1b272a7a7d FPGA/Cx4: introduce wait states (fix MMX2 attract mode) 2012-05-02 10:30:22 +02:00
Maximilian Rehkopf
812a796568 PCB: add logo to Rev.E2 2012-05-02 10:24:15 +02:00
Maximilian Rehkopf
0f3138124e add missing files cfg.[ch] and sysinfo.[ch] 2012-04-16 15:22:53 +02:00
ikari
ea82765686 menu: fix xscroll bug when leaving directory 2012-03-03 21:26:01 +01:00
123 changed files with 10062 additions and 10919 deletions

22
.gitignore vendored Normal file
View File

@@ -0,0 +1,22 @@
*.cod
*.hex
*.lst
*.o
*.diff
.DS_Store
*.o65
*.ips
*.bin
*.map
*.o.d
*.log
*.smc
*.sfc
*~
*.old
*.elf
*.img
autoconf.h
utils/rle
utils/derle
*.bit

View File

@@ -38,3 +38,59 @@ v0.1.3
* Some FPGA configuration error detection (mainly useful for hardware diag)
* Fixes:
- FPGA-side SD clock pullup (increases reliability with some cards)
v0.1.4
======
* SPC Player (contributed by necronomfive/blargg)
* System Information screen now shows CPU/PPU revision (contributed by necronomfive)
* Satellaview: basic data transmission packet support (makes some more games boot, thanks to LuigiBlood for assistance and sample data packets)
* Number of supported files increased to 50000 per card / 16380 per directory
* Slight speedup of menu text rendering
* Reduce load time of menu
* Adjust Cx4 timing to be more faithful
(Mega Man now defeats the boss in attract mode in Mega Man X2)
* adapt ROM mirroring size to file size if header information is invalid
(fixes Super Noah's Ark 3D, possibly others)
* MSU1 interface changes suggested by byuu:
- Data offset 0 and audio track 0 are automatically requested on reset.
This causes the busy flags to become 0 shortly after reset/startup.
- $2000 bit 3 is now "audio error", becomes valid after "audio busy" -> 0
set when an error occurred while preparing playback of the requested audio track
* write LED stays on when SRAM content changes constantly
* Fixes:
- fix empty save files on FAT16 / incorrect free cluster count on FAT32
- correct directory sorting (force parent directory at top of list)
- fix text corruption when entering a directory with a scrollable name
- fix files/dirs count in system information
- make 'sd2snes' directory hiding case-insensitive
- improve DAC I²S timing
- fix occasional palette corruption in menu
- fix SD clock glitch on ROM loading (occasional glitches/crashes)
- fix memory write timing on ROM loading (occasional glitches/crashes)
- fix SPI timing (ROMs not loading; System Information not working)
- properly synchronize SNES control signals (occasional glitches/crashes)
- fix floating IRQ output (occasional glitches/slowdowns)
v0.1.4a (bugfix release)
========================
* Fix DMA initialization in the menu (could cause sprite corruption in some games)
v0.1.5
======
* Sort directories by entire file name instead of first 20 characters only
* Correctly map SRAM larger than 8192 bytes (HiROM) / 32768 bytes (LoROM)
(fixes Dezaemon, Ongaku Tsukuuru - Kanadeeru)
* SPC player: fix soft fade-in (first note cut off) on S-APU consoles
(1CHIP / some Jr.)
* More accurate BS-X memory map
* Ignore input from non-standard controllers (Super Scope, Mouse etc.)
* Fixes:
- minor memory access timing tweaks
(should help with occasional glitches on some systems)

BIN
bin/bsxpage.bin Normal file

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
OBJS = header.ips reset.o65 main.o65 font.o65 palette.o65 data.o65 const.o65 logo.o65 logospr.o65 text.o65 dma.o65 menu.o65 pad.o65 time.o65 mainmenu.o65 sysinfo.o65 # gfx.o65 # vars.o65
OBJS = header.ips reset.o65 main.o65 font.o65 palette.o65 data.o65 const.o65 logo.o65 logospr.o65 text.o65 dma.o65 filesel.o65 pad.o65 time.o65 mainmenu.o65 sysinfo.o65 spc700.o65 spcplay.o65 # gfx.o65 # vars.o65
all: clean menu.bin map

View File

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

View File

@@ -1,41 +1,43 @@
.data
;don't anger the stack!
;----------parameters for text output----------
print_x .byt 0 ;x coordinate
.byt 0
print_y .byt 0 ;y coordinate
.byt 0
print_src .word 0 ;source data address
print_bank .byt 0 ;source data bank
print_pal .word 0 ;palette number for text output
print_temp .word 0 ;work variable
print_count .byt 0 ;how many characters may be printed?
print_count_tmp .byt 0 ;work variable
print_done .word 0 ;how many characters were printed?
print_x .byt 0 ; x coordinate
.byt 0
print_y .byt 0 ; y coordinate
.byt 0
print_src .word 0 ; source data address
print_bank .byt 0 ; source data bank
print_pal .word 0 ; palette number for text output
print_temp .word 0 ; work variable
print_count .byt 0 ; how many characters may be printed?
print_count_tmp .byt 0 ; work variable
print_done .word 0 ; how many characters were printed?
;----------parameters for dma----------
dma_a_bank .byt 0
dma_a_addr .word 0
dma_b_reg .byt 0
dma_len .word 0
dma_mode .byt 0
dma_a_bank .byt 0
dma_a_addr .word 0
dma_b_reg .byt 0
dma_len .word 0
dma_mode .byt 0
;----------state information----------
isr_done .byt 0 ; isr done flag
isr_done .byt 0 ; isr done flag
;----------menu layout/system constants (224/448)
textdmasize .word 0 ; number of bytes to copy each frame
textdmasize .word 0 ; number of bytes to copy each frame
infloop .byt 0,0 ; to be filled w/ 80 FE
infloop .byt 0,0 ; to be filled w/ 80 FE
printloop_wram .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
printloop_wram
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
loprint_wram .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
loprint_wram
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

View File

@@ -1,4 +1,4 @@
palette
;fonts
.byt $42, $08, $ff, $7f, $00, $00, $9c, $73
.byt $42, $08, $ff, $43, $00, $00, $18, $63
.byt $42, $08, $ff, $43, $00, $00, $18, $63

View File

@@ -11,24 +11,24 @@
; NMI - called on VBlank
NMI_ROUTINE:
sep #$20 : .as
rep #$10 : .xl
lda #$00
pha
plb
lda $4210
sep #$20 : .as
rep #$10 : .xl
lda #$00
pha
plb
lda $4210
ldx #BG1_TILE_BASE
stx $2116
DMA0(#$01, #36*64, #^BG1_TILE_BUF, #!BG1_TILE_BUF, #$18)
ldx #BG1_TILE_BASE
stx $2116
DMA0(#$01, #36*64, #^BG1_TILE_BUF, #!BG1_TILE_BUF, #$18)
lda #$01
sta isr_done
rtl
lda #$01
sta isr_done
rtl
; IRQ - called when triggered
IRQ_ROUTINE:
sep #$20 : .as
lda $4211 ;Acknowledge irq
rtl
sep #$20 : .as
lda $4211 ;Acknowledge irq
rtl

View File

@@ -168,4 +168,24 @@ text_mm_vmode_game .byt "Game video mode", 0
text_mm_sysinfo .byt "System Information", 0
text_statusbar_keys .byt "A:Select B:Back X:Menu", 0
text_last .byt "Run previous ROM: Press Start again to confirm", 0
text_system .byt "CPU Rev.: x PPU1 Rev.: y PPU2 Rev.: z",0
text_spcplay .byt "SPC Music Player", 0
spcplay_win_x .byt 15
spcplay_win_y .byt 15
spcplay_win_w .byt 33
spcplay_win_h .byt 5
text_spcload .byt "Loading SPC data to SPC700...", 0
text_spcstarta .byt "**** Now playing SPC tune ****", 0
text_spcstartb .byt "Name: ",0
text_spcstartc .byt "Song: ",0
text_spcstartd .byt "Artist:",0
spcstart_win_x .byt 10
spcstart_win_y .byt 13
spcstart_win_w .byt 44
spcstart_win_h .byt 9
text_spcid .byt "SNES-SPC700"

View File

@@ -16,7 +16,7 @@ dirend_onscreen .byt 0
dirlog_idx .byt 0,0,0 ; long ptr
direntry_fits_idx
.byt 0,0
longptr .byt 0,0,0 ; general purpose long ptr
;----------parameters for text output----------
print_x .byt 0 ;x coordinate
.byt 0
@@ -26,8 +26,8 @@ print_src .word 0 ;source data address
print_bank .byt 0 ;source data bank
print_pal .word 0 ;palette number for text output
print_temp .word 0 ;work variable
print_count .byt 0 ;how many characters may be printed?
print_count_tmp .byt 0 ;work variable
print_ptr .byt 0,0,0 ;read pointer
print_count .word 0 ;how many characters may be printed?
print_done .word 0 ;how many characters were printed?
print_over .byt 0 ;was the string printed incompletely?
;----------parameters for dma----------
@@ -45,9 +45,9 @@ bar_x .byt 0 ; pixel x position of select bar
bar_y .byt 0 ; pixel y position of select bar
bar_w .byt 0 ; bar width
bar_wl .byt 0 ; bar width
menu_state .byt 0 ; menu state (0=file select)
menu_dirty .byt 0 ; menu dirty (e.g. after state change or when redraw is needed)
menu_sel .word 0 ; selected item #
filesel_state .byt 0 ; menu state (0=file select)
filesel_dirty .byt 0 ; menu dirty (e.g. after state change or when redraw is needed)
filesel_sel .word 0 ; selected item #
cursor_x .byt 0 ; current cursor position (x)
cursor_y .byt 0 ; current cursor position (y)
fd_addr .word 0 ; address of current "file descriptor"
@@ -96,6 +96,8 @@ barstep .byt 0 ; step size for bar
;-misc
testvar .word 0,0,0,0
;menu system
menu_stack .word 0,0,0,0,0,0,0,0
;----------hdma tables in WRAM (must be stable when cartridge is cut off)
hdma_pal .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
@@ -183,5 +185,18 @@ direntry_xscroll
.word 0
direntry_xscroll_wait
.word 0
infloop .byt 0,0 ; to be filled w/ 80 FE
infloop .byt 0,0 ; to be filled w/ 80 FE
tgt_bright
.byt 0
cur_bright
.byt 0
;------------------------
saved_sp
.word 0
warm_signature
.word 0
snes_system_config
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
wram_fadeloop .byt 0

View File

@@ -1,21 +1,4 @@
dma0:
rep #$10 : .xl
sep #$20 : .as
lda dma_mode
sta $4300
lda dma_b_reg
sta $4301
lda dma_a_bank
ldx dma_a_addr
stx $4302
sta $4304
ldx dma_len
stx $4305
lda #$01
sta $420b
rts
setup_hdma:
sep #$20 : .as
rep #$10 : .xl
@@ -67,8 +50,11 @@ setup_hdma:
sty $4352
sta $4354
; lda #$06
; sta $420c ;enable HDMA ch. 1+2
lda #$3a
sta $420c ;enable HDMA ch. 1+3+4+5
jsr waitblank
lda #$3e
sta $420c ;enable HDMA ch. 2 too
lda #$81 ;VBlank NMI + Auto Joypad Read
sta $4200 ;enable V-BLANK NMI
rts

View File

@@ -1,13 +1,22 @@
#define hash #
#define f(x) x
#define imm(a) f(hash)a
#define DMA0(mode, len, a_bank, a_addr, b_reg)\
lda mode \
: sta dma_mode \
php \
: sep imm($20) : .as \
: rep imm($10) : .xl \
: lda mode \
: sta $4300 \
: ldx a_addr \
: lda a_bank \
: stx dma_a_addr \
: sta dma_a_bank \
: stx $4302 \
: sta $4304 \
: ldx len \
: stx dma_len \
: stx $4305 \
: lda b_reg \
: sta dma_b_reg \
: jsr dma0
: sta $4301 \
: lda imm($01) \
: sta $420b \
: plp

View File

@@ -1,7 +1,7 @@
#include "memmap.i65"
#include "dma.i65"
menu_init:
filesel_init:
sep #$20 : .as
rep #$10 : .xl
lda #^ROOT_DIR
@@ -10,7 +10,7 @@ menu_init:
stx dirptr_addr
sta dirstart_bank
stx dirstart_addr
stz menu_state
stz filesel_state
stz dirend_onscreen
lda #$02
sta cursor_x
@@ -22,11 +22,11 @@ menu_init:
sta bar_wl
ldx #$0000
stx dirptr_idx
stx menu_sel
stx filesel_sel
stx direntry_xscroll
stx direntry_xscroll_state
lda #$01
sta menu_dirty
sta filesel_dirty
rep #$20 : .al
lda #!dirlog
sta dirlog_idx
@@ -35,40 +35,39 @@ menu_init:
sta dirlog_idx+2
rts
menuloop:
menuloop_s1
fileselloop:
fileselloop_s1
sep #$20 : .as
rep #$10 : .xl
lda isr_done
lsr
bcc menuloop_s1
bcc fileselloop_s1
stz isr_done
jsr printtime
jsr menu_updates ;update stuff, check keys etc
lda menu_dirty ;is there ANY reason to redraw the menu?
jsr filesel_updates ;update stuff, check keys etc
lda filesel_dirty ;is there ANY reason to redraw the menu?
cmp #$01
beq menuloop_redraw ;then do
beq fileselloop_redraw ;then do
jsr scroll_direntry
bra menuloop_s1
menuloop_redraw
stz menu_dirty
jsr menu_statusbar
jsr menu_redraw
jsr menu_cleanup ;update phase 2
bra menuloop_s1
bra fileselloop_s1
fileselloop_redraw
stz filesel_dirty
jsr filesel_statusbar
jsr filesel_redraw
jsr filesel_cleanup ;update phase 2
bra fileselloop_s1
rts
menu_cleanup:
filesel_cleanup:
sep #$20 : .as
rep #$10 : .xl
lda dirend_onscreen ;end of file list on screen?
beq menu_cleanup_out ;
beq filesel_cleanup_out ;
lda dirend_idx
lsr
lsr
pha
menu_cleanup_loop ;pad rest of screen with empty lines
filesel_cleanup_loop ;pad rest of screen with empty lines
cmp listdisp ;end of screen reached?
beq + ;then leave
pha
@@ -87,24 +86,24 @@ menu_cleanup_loop ;pad rest of screen with empty lines
jsr hiprint
pla
inc
bra menu_cleanup_loop
bra filesel_cleanup_loop
+
pla
cmp menu_sel
beq menu_cleanup_out
bpl menu_cleanup_out
sta menu_sel
menu_cleanup_out
cmp filesel_sel
beq filesel_cleanup_out
bpl filesel_cleanup_out
sta filesel_sel
filesel_cleanup_out
rts
menu_updates:
filesel_updates:
;update selection, scroll etc
lda menu_sel
lda filesel_sel
asl
asl
sta dirptr_idx
lda menu_sel
lda filesel_sel
clc
adc #$08
sta bar_yl
@@ -141,47 +140,47 @@ menu_updates:
lda #$40
and pad1trig
bne key_x
bra menuupd_out
bra fileselupd_out
key_down
jsr menu_key_down
bra menuupd_out
jsr filesel_key_down
bra fileselupd_out
key_up
jsr menu_key_up
bra menuupd_out
jsr filesel_key_up
bra fileselupd_out
key_right
jsr menu_key_right
bra menuupd_out
jsr filesel_key_right
bra fileselupd_out
key_left
jsr menu_key_left
bra menuupd_out
jsr filesel_key_left
bra fileselupd_out
key_b
jsr menu_key_b
bra menuupd_out
jsr filesel_key_b
bra fileselupd_out
key_a
jsr menu_key_a
bra menuupd_out
jsr filesel_key_a
bra fileselupd_out
key_x
jsr menu_key_x
bra menuupd_out
jsr filesel_key_x
bra fileselupd_out
key_select
jsr menu_key_select
bra menuupd_out
jsr filesel_key_select
bra fileselupd_out
key_start
jsr menu_key_start
bra menuupd_out
jsr filesel_key_start
bra fileselupd_out
menuupd_out
fileselupd_out
lda #$09
sta cursor_y
rts
menu_redraw:
lda menu_state
filesel_redraw:
lda filesel_state
beq redraw_filelist
; cmp 1
; beq redraw_main
menu_redraw_out
filesel_redraw_out
rts
redraw_filelist
@@ -237,7 +236,7 @@ redraw_filelist_last ;check if next offscreen item is end of dir
redraw_filelist_out
ldx #$0000
stx dirptr_idx
brl menu_redraw_out
brl filesel_redraw_out
print_direntry:
lda cursor_y
@@ -272,6 +271,10 @@ dirent_is_file
lda #$0000
bra dirent_type_cont
+
cmp #$0003 ;SPC -> palette 2
bne +
lda #$0002
bra dirent_type_cont
cmp #$0004 ;IPS -> palette 2 (green)
bne +
lda #$0002
@@ -352,14 +355,14 @@ dirent_type_cont_2
rts
menu_key_down:
filesel_key_down:
jsr scroll_direntry_clean
lda listdisp
dec
cmp menu_sel
cmp filesel_sel
bne down_noscroll
lda #$01
sta menu_dirty
sta filesel_dirty
lda dirend_onscreen
bne down_out
rep #$20 : .al
@@ -377,21 +380,21 @@ down_noscroll
lda dirend_idx
lsr
lsr
cmp menu_sel
beq menuupd_lastcursor
bcc menuupd_lastcursor
+ lda menu_sel
cmp filesel_sel
beq fileselupd_lastcursor
bcc fileselupd_lastcursor
+ lda filesel_sel
inc
sta menu_sel
sta filesel_sel
down_out
rts
menu_key_up:
filesel_key_up:
jsr scroll_direntry_clean
lda menu_sel
lda filesel_sel
bne up_noscroll
lda #$01
sta menu_dirty
sta filesel_dirty
rep #$20 : .al
lda dirptr_addr
cmp dirstart_addr
@@ -404,25 +407,25 @@ menu_key_up:
bra up_out
up_noscroll
dec
sta menu_sel
sta filesel_sel
up_out
sep #$20 : .as
rts
menuupd_lastcursor
fileselupd_lastcursor
jsr scroll_direntry_clean
lda dirend_idx
lsr
lsr
sta menu_sel
sta filesel_sel
rts
; go back one page
menu_key_left:
filesel_key_left:
stz direntry_xscroll
stz direntry_xscroll_state
lda #$01 ; must redraw afterwards
sta menu_dirty
sta filesel_dirty
rep #$20 : .al
lda dirptr_addr ; get current direntry pointer
beq + ; special case: if 0, we are at the first entry in memory
@@ -441,18 +444,18 @@ menu_key_left:
sep #$20 : .as
rts
+ lda dirstart_addr ; reset pointer to start of directory
stz menu_sel ; reset the selection cursor too
stz filesel_sel ; reset the selection cursor too
bra -
; go forth one page
menu_key_right:
filesel_key_right:
stz direntry_xscroll
stz direntry_xscroll_state
sep #$20 : .as
lda dirend_onscreen
bne menuupd_lastcursor
bne fileselupd_lastcursor
lda #$01
sta menu_dirty
sta filesel_dirty
rep #$20 : .al
lda listdisp
asl
@@ -463,24 +466,26 @@ menu_key_right:
sep #$20 : .as
rts
menu_key_a:
filesel_key_a:
jsr select_item
rts
menu_key_select:
filesel_key_select:
rts
menu_key_start:
filesel_key_start:
jsr select_last_file
rts
menu_key_b:
filesel_key_b:
stz direntry_xscroll
stz direntry_xscroll_state
rep #$20 : .al
lda dirstart_addr
beq skip_key_b
sta dirptr_addr
lda #$0000
sta menu_sel
sta filesel_sel
bra select_item
skip_key_b
sep #$20 : .as
@@ -488,7 +493,7 @@ skip_key_b
select_item:
rep #$20 : .al
lda menu_sel
lda filesel_sel
and #$00ff
asl
asl
@@ -500,6 +505,8 @@ select_item:
lda [dirptr_addr], y
cmp #$01
beq sel_is_file
cmp #$03
beq sel_is_spc
cmp #$04
beq sel_is_file
cmp #$80
@@ -517,25 +524,28 @@ sel_is_parent
sel_is_dir
jsr select_dir
bra select_item_cont
sel_is_spc
jsr select_spc
bra select_item_cont
select_file:
; have avr load the rom
; have MCU load the rom
dey
rep #$20 : .al
lda [dirptr_addr], y
and #$00ff
sta @AVR_PARAM+2
sta @MCU_PARAM+2
dey
dey
lda [dirptr_addr], y
sta @AVR_PARAM
sta @MCU_PARAM
sep #$20 : .as
lda #$01
sta @AVR_CMD
select_file_fade:
lda #$00
sta @$4200
sei
lda #$01
sta @MCU_CMD
select_file_fade:
jsl @wram_fadeloop
rts
@@ -558,7 +568,7 @@ select_dir:
lda @dirptr_bank
sta [dirlog_idx], y
iny
lda @menu_sel
lda @filesel_sel
sta [dirlog_idx], y
lda @dirlog_idx
clc
@@ -594,10 +604,12 @@ select_dir:
sta @dirptr_addr
sta @dirstart_addr
lda #$0000
sta @menu_sel
sta @filesel_sel
sta @direntry_xscroll
sta @direntry_xscroll_state
sep #$20 : .as
lda #$01
sta @menu_dirty
sta @filesel_dirty
plb
rts
@@ -626,14 +638,35 @@ select_parent:
sta @dirptr_bank
iny
rep #$20 : .al
lda [dirlog_idx], y ; load menu_sel
sta @menu_sel
lda [dirlog_idx], y ; load filesel_sel
sta @filesel_sel
sep #$20 : .as
lda #$01
sta @menu_dirty
sta @filesel_dirty
rts
menu_key_x:
select_spc:
dey
rep #$20 : .al
lda [dirptr_addr], y
and #$00ff
sta @MCU_PARAM+2
dey
dey
lda [dirptr_addr], y
sta @MCU_PARAM
sep #$20 : .as
lda #CMD_LOADSPC
sta @MCU_CMD
wait_spc:
lda @MCU_CMD
cmp #$00
bne wait_spc
jsr spcplayer
jsr restore_screen
rts
filesel_key_x:
jsr mainmenu
rts
@@ -643,11 +676,11 @@ setup_224:
lda #18
sta listdisp
dec
cmp menu_sel
cmp filesel_sel
bmi setup_224_adjsel
bra +
setup_224_adjsel
sta menu_sel
sta filesel_sel
+
lda #18*64
sta textdmasize
@@ -666,7 +699,7 @@ setup_224_adjsel
sta hdma_math_selection
stz vidmode
lda #$01
sta menu_dirty
sta filesel_dirty
lda #^space64
ldx #!space64
sta print_bank
@@ -686,7 +719,7 @@ setup_224_adjsel
plp
rts
menu_statusbar
filesel_statusbar
pha
phx
php
@@ -772,7 +805,7 @@ select_last_file:
and pad1trig+1
beq -
lda #$04
sta @AVR_CMD
sta @MCU_CMD
jmp select_file_fade
+ jsr restore_screen
plp
@@ -789,7 +822,7 @@ scroll_direntry_clean:
rts
scroll_direntry:
ldy menu_sel
ldy filesel_sel
lda direntry_xscroll_state
bne +
lda direntry_fits, y
@@ -819,7 +852,7 @@ scroll_direntry_scrollfast
lda #$02
sta cursor_x
rep #$20 : .al
lda menu_sel
lda filesel_sel
asl
asl
tay
@@ -836,7 +869,7 @@ scroll_direntry_scrollfast
lda [dirptr_addr], y
iny
sta @dirent_type
ldy menu_sel
ldy filesel_sel
sty direntry_fits_idx
phy
jsr print_direntry
@@ -848,6 +881,7 @@ scroll_direntry_scrollfast
lda #$28
sta direntry_xscroll_wait
+ lda direntry_xscroll_state
clc
adc direntry_xscroll
sta direntry_xscroll
bne +

View File

@@ -4,78 +4,179 @@
GAME_MAIN:
sep #$20 : .as
lda #$00
sta @AVR_CMD
sta @MCU_CMD ; clear MCU command register
rep #$20 : .al
lda #$0000
sta @AVR_PARAM
sta @AVR_PARAM+2
sta @MCU_PARAM ; clear MCU command parameters
sta @MCU_PARAM+2
sep #$20 : .as
stz $4200 ; inhibit VBlank NMI
jsr killdma
rep #$20 : .al
lda @warm_signature ; Was CMD_RESET issued before reset?
cmp #$fa50 ; If yes, then perform warm boot procedure
bne coldboot
lda #$0000
sta @warm_signature
lda @saved_sp ; Restore previous stack pointer
tcs
sep #$20 : .as
; jsr killdma ; The following initialization processes must not touch memory
jsr waitblank ; structures used by the file selector !
jsr snes_init
cli
lda #$01
sta $420d ; fast cpu
jsr setup_gfx
jsr colortest
jsr video_init
jsr setup_hdma
lda #$0f
sta cur_bright
sta tgt_bright
sta $2100
jmp @set_bank ; Set bios bank, just to be sure
set_bank:
plp ; Restore processor state
rts ; Jump to the routine which called the sub-routine issuing CMD_RESET
coldboot: ; Regular, cold-start init
sep #$20 : .as
; jsr killdma
jsr waitblank
jsr snes_init
lda #$01
sta $420d ; fast cpu
jsr setup_gfx
jsr colortest
jsr filesel_init
jsr video_init
jsr setup_hdma
jsr menu_init
jsr tests
jsr screen_on
sep #$20 : .as
lda @RTC_STATUS
beq +
jsl time_init
+
jsr menuloop
jsr fileselloop
cli
stz $4200
jmp @infloop ;infinite loop in WRAM
killdma:
stz $420b
stz $420c
stz $4300
stz $4301
stz $4302
stz $4303
stz $4304
stz $4305
stz $4306
stz $4307
stz $4308
stz $4309
stz $430a
stz $430b
stz $4310
stz $4311
stz $4312
stz $4313
stz $4314
stz $4315
stz $4316
stz $4317
stz $4318
stz $4319
stz $431a
stz $431b
stz $4320
stz $4321
stz $4322
stz $4323
stz $4324
stz $4325
stz $4326
stz $4327
stz $4328
stz $4329
stz $432a
stz $432b
stz $4330
stz $4331
stz $4332
stz $4333
stz $4334
stz $4335
stz $4336
stz $4337
stz $4338
stz $4339
stz $433a
stz $433b
stz $4340
stz $4341
stz $4342
stz $4343
stz $4344
stz $4345
stz $4346
stz $4347
stz $4348
stz $4349
stz $434a
stz $434b
stz $4350
stz $4351
stz $4352
stz $4353
stz $4354
stz $4355
stz $4356
stz $4357
stz $4358
stz $4359
stz $435a
stz $435b
stz $4360
stz $4361
stz $4362
stz $4363
stz $4364
stz $4365
stz $4366
stz $4367
stz $4368
stz $4369
stz $436a
stz $436b
stz $4370
stz $4371
stz $4372
stz $4373
stz $4374
stz $4375
stz $4376
stz $4377
stz $4378
stz $4379
stz $437a
stz $437b
stz $420b
stz $420c
rts
waitblank:
php
sep #$30 : .as : .xs
- lda $4212
and #$80
bne -
- lda $4212
and #$80
beq -
plp
rts
colortest:
@@ -91,11 +192,11 @@ setup_gfx:
stz $420b
stz $420c
;clear tilemap buffers
ldx #$0000
ldx #$8000
stx $2181
lda #$01
lda #$00
sta $2183
DMA0(#$08, #0, #^zero, #!zero, #$80)
DMA0(#$08, #$8000, #^zero, #!zero, #$80)
;generate fonts
jsr genfonts
@@ -113,7 +214,7 @@ setup_gfx:
;clear OAM tables
ldx #$0000
stx $2102
DMA0(#$08, #$544, #^zero, #!zero, #$04)
DMA0(#$08, #$220, #^zero, #!zero, #$04)
;copy logo tiles
ldx #$2000
@@ -146,6 +247,7 @@ setup_gfx:
;set palette
stz $2121
DMA0(#$00, #$200, #^palette, #!palette, #$22)
stz $2121
;copy hdma tables so we can work "without" the cartridge
;palette
@@ -195,10 +297,10 @@ setup_gfx:
DMA0(#$00, #$6C, #^fadeloop, #!fadeloop, #$80);
rts
tests:
video_init:
sep #$20 : .as ;8-bit accumulator
rep #$10 : .xl ;16-bit index
lda #$03 ;mode 3, mode 5 via HDMA :D
lda #$03 ;mode 3, mode 5 via HDMA
sta $2105
lda #$58 ;Tilemap addr 0xB000
ora #$02 ;SC size 32x64
@@ -224,11 +326,17 @@ tests:
lda #$1f
sta $212e
sta $212f
stz $2121
lda #$0f
sta $2100 ;screen on, full brightness
lda #9
; stz $2121
lda #8
sta bar_yl
stz cur_bright
stz tgt_bright
rts
screen_on:
stz $2100 ;screen on, 0% brightness
lda #$0f
sta tgt_bright
rts
snes_init:
@@ -248,6 +356,7 @@ snes_init:
stz $420a ;
stz $420b ;
stz $420c ;
stz $420d ;
lda #$8f
sta $2100 ;INIDISP: force blank
lda #$03 ; 8x8+16x16; name=0; base=3
@@ -339,7 +448,7 @@ snes_init:
fadeloop:
sep #$30 : .as : .xs
ldx #$0f
ldx cur_bright
and #$00
pha
plb

View File

@@ -80,15 +80,12 @@ mm_entloop
plb
phx
jsr hiprint
plx
inx
inx
inx
inx
inx
inx
inx
inx
rep #$20 : .al
pla
clc
adc #$08
tax
sep #$20 : .as
inc mm_tmp
lda mm_tmp
cmp @main_entries

View File

@@ -6,19 +6,24 @@
/* These must be defined as constants, because they're used
* in calculation that is sent to PPU as parameters */
#define APUIO0 $2140
#define APUIO1 $2141
#define APUIO2 $2142
#define APUIO3 $2143
#define BG1_TILE_BASE $5800
#define BG2_TILE_BASE $5000
#define OAM_TILE_BASE $6000
#define BG1_TILE_BUF $7FB000
#define BG2_TILE_BUF $7FA000
#define BG1_TILE_BUF $7EB000
#define BG2_TILE_BUF $7EA000
#define BG1_TILE_BAK $7F9000
#define BG2_TILE_BAK $7F8000
#define BG1_TILE_BAK $7E9000
#define BG2_TILE_BAK $7E8000
#define AVR_CMD $307000
#define AVR_PARAM $307004
#define MCU_CMD $307000
#define MCU_PARAM $307004
#define RTC_STATUS $307100
#define LAST_STATUS $307101
#define SYSINFO_BLK $307200
@@ -27,3 +32,9 @@
#define ROOT_DIR $C10000
#define CMD_SYSINFO $03
#define CMD_LOADSPC $05
#define CMD_RESET $06
#define SPC_DATA $FD0000
#define SPC_HEADER $FE0000
#define SPC_DSP_REGS $FE0100

View File

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

View File

@@ -84,9 +84,29 @@ math_cont
clc
adc bar_x ; + X start coord
sta $2127 ; window 1 right
lda #$3e ; ch. 1-5
sta @$420c ; trigger HDMA
lda #$01
; lda #$3e ; ch. 1-5
; sta @$420c ; trigger HDMA
lda cur_bright
cmp tgt_bright
beq +
bpl bright_down
bright_up
inc
sta cur_bright
lda $2100
and #$f0
ora cur_bright
sta $2100
bra +
bright_down
dec
sta cur_bright
lda $2100
and #$f0
ora cur_bright
sta $2100
+ lda #$01
sta isr_done
rtl

61
snes/spc700.a65 Normal file
View File

@@ -0,0 +1,61 @@
; All SPC700 routines in SPC700 machine code
; SPC loader & transfer routines by Shay Green <gblargg@gmail.com>
loader ; .org $0002
.byt $F8,$21 ; mov x,@loader_data
.byt $BD ; mov sp,x
.byt $CD,$22 ; mov x,#@loader_data+1
; Push PC and PSW from SPC header
.byt $BF ; mov a,(x)+
.byt $2D ; push a
.byt $BF ; mov a,(x)+
.byt $2D ; push a
.byt $BF ; mov a,(x)+
.byt $2D ; push a
; Set FLG to $60 rather than value from SPC
.byt $E8,$60 ; mov a,#$60
.byt $D4,$6C ; mov FLG+x,a
; Restore DSP registers
.byt $8D,$00 ; mov y,#0
.byt $BF ; next: mov a,(x)+
.byt $CB,$F2 ; mov $F2,y
.byt $C4,$F3 ; mov $F3,a
.byt $FC ; inc y
.byt $10,-8 ; bpl next
.byt $8F,$6C,$F2 ; mov $F2,#FLG ; set for later
; Rerun loader
.byt $5F,$C0,$FF ; jmp $FFC0
;---------------------------------------
transfer ; .org $0002
.byt $CD,$FE ; mov x,#$FE ; transfer 254 pages
; Transfer four-byte chunks
.byt $8D,$3F ; page: mov y,#$3F
.byt $E4,$F4 ; quad: mov a,$F4
.byt $D6,$00,$02 ; mov0: mov !$0200+y,a
.byt $E4,$F5 ; mov a,$F5
.byt $D6,$40,$02 ; mov1: mov !$0240+y,a
.byt $E4,$F6 ; mov a,$F6
.byt $D6,$80,$02 ; mov2: mov !$0280+y,a
.byt $E4,$F7 ; mov a,$F7 ; tell S-CPU we're ready for more
.byt $CB,$F7 ; mov $F7,Y
.byt $D6,$C0,$02 ; mov3: mov !$02C0+y,a
.byt $DC ; dec y
.byt $10,-25 ; bpl quad
; Increment MSBs of addresses
.byt $AB,$0A ; inc mov0+2
.byt $AB,$0F ; inc mov1+2
.byt $AB,$14 ; inc mov2+2
.byt $AB,$1B ; inc mov3+2
.byt $1D ; dec x
.byt $D0,-38 ; bne page
; Rerun loader
.byt $5F,$C0,$FF ; jmp $FFC0

676
snes/spcplay.a65 Normal file
View File

@@ -0,0 +1,676 @@
#include "memmap.i65"
; SPC Player
; SPC700 transfer and IO routines by Shay Green <gblargg@gmail.com>
spcplayer:
php
sep #$30 : .as : .xs
ldx #$0a ; Check if SPC header is present
-
lda @SPC_HEADER,x
cmp @text_spcid,x
beq +
jmp spc_exit
+
dey
bne -
rep #$10 : .xl ; Now draw lots of stuff
stz bar_wl
dec bar_wl
stz bar_xl
dec bar_xl
stz bar_yl
dec bar_yl
jsr backup_screen
lda #^text_spcplay ; Loading window
sta window_tbank
ldx #!text_spcplay
stx window_taddr
lda @spcplay_win_x
sta window_x
lda @spcplay_win_y
sta window_y
lda @spcplay_win_w
sta window_w
lda @spcplay_win_h
sta window_h
jsr draw_window
lda #^text_spcload ; Loading text
ldx #!text_spcload
sta print_bank
stx print_src
stz print_pal
lda #29
sta print_count
lda #17
sta print_y
lda #17
sta print_x
jsr hiprint
stz isr_done
-
lda isr_done ; Wait until text is being printed...
beq -
jsr spc700_load ; Load SPC into SPC700
lda #^text_spcplay
sta window_tbank
ldx #!text_spcplay
stx window_taddr
lda @spcstart_win_x
sta window_x
lda @spcstart_win_y
sta window_y
lda @spcstart_win_w
sta window_w
lda @spcstart_win_h
sta window_h
jsr draw_window
lda #^text_spcstarta
ldx #!text_spcstarta
sta print_bank
stx print_src
lda #$01
sta print_pal
lda #30
sta print_count
lda #15
sta print_y
lda #17
sta print_x
jsr hiprint
lda #^text_spcstartb
ldx #!text_spcstartb
sta print_bank
stx print_src
lda #$01
sta print_pal
lda #07
sta print_count
lda #17
sta print_y
lda #12
sta print_x
jsr hiprint
lda #$fe
ldx #$004e
sta print_bank
stx print_src
stz print_pal
lda #32
sta print_count
lda #17
sta print_y
lda #20
sta print_x
jsr hiprint
lda #^text_spcstartc
ldx #!text_spcstartc
sta print_bank
stx print_src
lda #$01
sta print_pal
lda #07
sta print_count
lda #18
sta print_y
lda #12
sta print_x
jsr hiprint
lda #$fe
ldx #$002e
sta print_bank
stx print_src
stz print_pal
lda #32
sta print_count
lda #18
sta print_y
lda #20
sta print_x
jsr hiprint
lda #^text_spcstartd
ldx #!text_spcstartd
sta print_bank
stx print_src
lda #$01
sta print_pal
lda #07
sta print_count
lda #19
sta print_y
lda #12
sta print_x
jsr hiprint
lda #$fe
ldx #$00b0
sta longptr+2
sta print_bank
stx longptr
ldy #$00
lda [longptr], y
cmp #$41
bpl +
inx
+ stx print_src
stz print_pal
lda #32
sta print_count
lda #19
sta print_y
lda #20
sta print_x
jsr hiprint
spc_playloop:
lda isr_done ; SPC player loop
lsr
bcc spc_playloop
jsr printtime
stz isr_done
jsr read_pad
lda #$80
and pad1trig+1
bne spc_key_b
bra spc_playloop
spc_key_b:
rep #$20 : .al
tsc
sta saved_sp ; Save SP for later re-entry
lda #$fa50 ; Write reset signature
sta @warm_signature
sep #$20 : .as
sei ; Blank screen & issue CMD_RESET command to Microcontroller...
stz $2100 ; ...this is required, because there is no other way to stop S-SMP & S-DSP
lda #CMD_RESET
sta @MCU_CMD
-
bra - ; At this point, the SNES waits for an external reset from the Microcontroller
spc_exit: ; Return from player in case of wrong SPC file data
plp
rts
;---------------------------------------
spc700_load:
php
sep #$20 : .as
rep #$10 : .xl
sei ; Disable NMI & IRQ
stz $4200 ; The SPC player code is really timing sensitive ;)
jsr upload_dsp_regs ; Upload S-DSP registers
jsr upload_high_ram ; Upload 63.5K of SPC700 ram
jsr upload_low_ram ; Upload rest of ram
jsr restore_final ; Restore SPC700 state & start execution
lda #$81 ; VBlank NMI + Auto Joypad Read
sta $4200 ; enable V-BLANK NMI
cli
plp
rts
;---------------------------------------
; Uploads DSP registers and some other setup code
upload_dsp_regs:
; ---- Begin upload
ldy #$0002
jsr spc_begin_upload
; ---- Upload loader
ldx #$0000
-
lda @loader,x
jsr spc_upload_byte
inx
cpy #31 ; size of loader
bne -
; ---- Upload SP, PC & PSW
lda @SPC_HEADER+43
jsr spc_upload_byte
lda @SPC_HEADER+38
jsr spc_upload_byte
lda @SPC_HEADER+37
jsr spc_upload_byte
lda @SPC_HEADER+42
jsr spc_upload_byte
; ---- Upload DSP registers
ldx #$0000
-
; initialize FLG and KON ($6c/$4c) to avoid artifacts
cpx #$4C
bne +
lda #$00
bra upload_skip_load
+
cpx #$6C
bne +
lda #$E0
bra upload_skip_load
+
lda @SPC_DSP_REGS,x
upload_skip_load
jsr spc_upload_byte
inx
cpx #128
bne -
; --- Upload fixed values for $F1-$F3
ldy #$00F1
jsr spc_next_upload
lda #$80 ; stop timers
jsr spc_upload_byte
lda #$6c ; get dspaddr set for later
jsr spc_upload_byte
lda #$60
jsr spc_upload_byte
; ---- Upload $f8-$1ff
ldy #$00F8
jsr spc_next_upload
ldx #$00F8
-
lda @SPC_DATA,x
jsr spc_upload_byte
inx
cpx #$200
bne -
; ---- Execute loader
ldy #$0002
jsr spc_execute
rts
;---------------------------------------
upload_high_ram:
ldy #$0002
jsr spc_begin_upload
; ---- Upload transfer routine
ldx #$0000
-
lda @transfer,x
jsr spc_upload_byte
inx
cpy #43 ; size of transfer routine
bne -
ldx #$023f ; prepare transfer address
; ---- Execute transfer routine
ldy #$0002
sty APUIO2
stz APUIO1
lda APUIO0
inc
inc
sta APUIO0
; Wait for acknowledgement
-
cmp APUIO0
bne -
; ---- Burst transfer of 63.5K using custom routine
outer_transfer_loop:
ldy #$003f ; 3
inner_transfer_loop:
lda @SPC_DATA,x ; 5 |
sta APUIO0 ; 4 |
lda @SPC_DATA+$40,x ; 5 |
sta APUIO1 ; 4 |
lda @SPC_DATA+$80,x ; 5 |
sta APUIO2 ; 4 |
lda @SPC_DATA+$C0,x ; 5 |
sta APUIO3 ; 4 |
tya ; 2 >> 38 cycles
-
cmp APUIO3 ; 4 |
bne - ; 3 |
dex ; 2 |
dey ; 2 |
bpl inner_transfer_loop ; 3 >> 14 cycles
rep #$21 : .al ; 3 |
txa ; 2 |
adc #$140 ; 3 |
tax ; 2 |
sep #$20 : .as ; 3 |
cpx #$003f ; 3 |
bne outer_transfer_loop ; 3 >> 19 cycles
rts
;---------------------------------------
upload_low_ram:
; ---- Upload $0002-$00EF using IPL
ldy #$0002
jsr spc_begin_upload
ldx #$0002
-
lda @SPC_DATA,x
jsr spc_upload_byte
inx
cpx #$00F0
bne -
rts
;---------------------------------------
; Executes final restoration code
restore_final:
jsr start_exec_io ; prepare execution from I/O registers
stz $420d ; SPC700 I/O code requires SLOW timing
; ---- Restore first two bytes of RAM
lda @SPC_DATA
xba
lda #$e8 ; MOV A,#@SPC_DATA
tax
jsr exec_instr
ldx #$00C4 ; MOV $00,A
jsr exec_instr
lda @SPC_DATA+1
xba
lda #$e8 ; MOV A,#@SPC_DATA+1
tax
jsr exec_instr
ldx #$01C4 ; MOV $01,A
jsr exec_instr
; ---- Restore SP
lda @SPC_HEADER+43
sec
sbc #3
xba
lda #$cd ; MOV X,#@SPC_HEADER+43
tax
jsr exec_instr
ldx #$bd ; MOV SP,X
jsr exec_instr
; ---- Restore X
lda @SPC_HEADER+40
xba
lda #$cd ; MOV X,#@SPC_HEADER+40
tax
jsr exec_instr
; ---- Restore Y
lda @SPC_HEADER+41
xba
lda #$8d ; MOV Y,#@SPC_HEADER+41
tax
jsr exec_instr
; ---- Restore DSP FLG register
lda @SPC_DSP_REGS+$6c
xba
lda #$e8 ; MOV A,#@SPC_DSP_REGS+$6c
tax
jsr exec_instr
ldx #$f3C4 ; MOV $f3,A -> $f2 has been set-up before by SPC700 loader
jsr exec_instr
; ---- wait a bit (the newer S-APU takes its time to ramp up the volume)
lda #$10
- pha
jsr waitblank
pla
dec
bne -
; ---- Restore DSP KON register
lda #$4C
xba
lda #$e8 ; MOV A,#$4c
tax
jsr exec_instr
ldx #$f2C4 ; MOV $f2,A
jsr exec_instr
lda @SPC_DSP_REGS+$4C
xba
lda #$e8 ; MOV A,#@SPC_DSP_REGS+$4c
tax
jsr exec_instr
ldx #$f3C4 ; MOV $f3,A
jsr exec_instr
; ---- Restore DSP register address
lda @SPC_DATA+$F2
xba
lda #$e8 ; MOV A,#@SPC_DATA+$F2
tax
jsr exec_instr
ldx #$f2C4 ; MOV dest,A
jsr exec_instr
; ---- Restore CONTROL register
lda @SPC_DATA+$F1
and #$CF ; don't clear input ports
xba
lda #$e8 ; MOV A,#@SPC_DATA+$F1
tax
jsr exec_instr
ldx #$f1C4 ; MOV $F1,A
jsr exec_instr
;---- Restore A
lda @SPC_HEADER+39
xba
lda #$e8 ; MOV A,#@SPC_HEADER+39
tax
jsr exec_instr
;---- Restore PSW and PC
ldx #$7F00 ; NOP; RTI
stx APUIO0
lda #$FC ; Patch loop to execute instruction just written
sta APUIO3
;---- restore IO ports $f4 - $f7
rep #$20 : .al
lda @SPC_DATA+$F4
tax
lda @SPC_DATA+$F6
sta APUIO2
stx APUIO0 ; last to avoid overwriting RETI before run
sep #$20 : .as
lda #$01
sta $420d ; restore FAST CPU operation
rts
;---------------------------------------
spc_begin_upload:
sty APUIO2 ; Set address
ldy #$BBAA ; Wait for SPC
-
cpy APUIO0
bne -
lda #$CC ; Send acknowledgement
sta APUIO1
sta APUIO0
- ; Wait for acknowledgement
cmp APUIO0
bne -
ldy #0 ; Initialize index
rts
;---------------------------------------
spc_upload_byte:
sta APUIO1
tya ; Signal it's ready
sta APUIO0
- ; Wait for acknowledgement
cmp APUIO0
bne -
iny
rts
;---------------------------------------
spc_next_upload:
sty APUIO2
; Send command
; Special case operation has been fully tested.
lda APUIO0
inc
inc
bne +
inc
+
sta APUIO1
sta APUIO0
; Wait for acknowledgement
-
cmp APUIO0
bne -
ldy #0
rts
;---------------------------------------
spc_execute:
sty APUIO2
stz APUIO1
lda APUIO0
inc
inc
sta APUIO0
; Wait for acknowledgement
-
cmp APUIO0
bne -
rts
;---------------------------------------
start_exec_io:
; Set execution address
ldx #$00F5
stx APUIO2
stz APUIO1 ; NOP
ldx #$FE2F ; BRA *-2
; Signal to SPC that we're ready
lda APUIO0
inc
inc
sta APUIO0
; Wait for acknowledgement
-
cmp APUIO0
bne -
; Quickly write branch
stx APUIO2
rts
;---------------------------------------
exec_instr:
; Replace instruction
stx APUIO0
lda #$FC
sta APUIO3 ; 30
; SPC BRA loop takes 4 cycles, so it reads
; the branch offset every 4 SPC cycles (84 master).
; We must handle the case where it read just before
; the write above, and when it reads just after it.
; If it reads just after, we have at least 7 SPC
; cycles (147 master) to change restore the branch
; offset.
; 48 minimum, 90 maximum
ora #0
ora #0
ora #0
nop
nop
nop
; 66 delay, about the middle of the above limits
phd ;4
pld ;5
; Give plenty of extra time if single execution
; isn't needed, as this avoids such tight timing
; requirements.
; phd ;4
; pld ;5
; phd ;4
; pld ;5
; Patch loop to skip first two bytes
lda #$FE ; 16
sta APUIO3 ; 30
; 38 minimum (assuming 66 delay above)
phd ; 4
pld ; 5
; Give plenty of extra time if single execution
; isn't needed, as this avoids such tight timing
; requirements.
phd
pld
phd
pld
rts

View File

@@ -35,11 +35,19 @@ show_sysinfo:
sta window_h
jsr draw_window
stz print_pal
ldx #38
copy_snes_system_text:
lda @text_system,x
sta @snes_system_config,x
dex
bpl copy_snes_system_text
sysinfo_printloop:
sep #$20 : .as
rep #$10 : .xl
lda #CMD_SYSINFO
sta @AVR_CMD
sta @MCU_CMD
lda #^SYSINFO_BLK
ldx #!SYSINFO_BLK
sta print_bank
@@ -51,7 +59,7 @@ sysinfo_printloop:
sta print_x
lda #40
sta print_count
lda #13
lda #12
- pha
jsr hiprint
inc print_y
@@ -64,6 +72,41 @@ sysinfo_printloop:
pla
dec
bne -
ldx #24
lda $213e
and #$0f
clc
adc #$30
sta @snes_system_config,x
ldx #38
lda $213f
and #$0f
clc
adc #$30
sta @snes_system_config,x
ldx #10
lda $4210
and #$0f
clc
adc #$30
sta @snes_system_config,x
lda #^snes_system_config ; System text
ldx #!snes_system_config
sta print_bank
stx print_src
stz print_pal
lda #39
sta print_count
lda #23
sta print_y
lda #12
sta print_x
jsr hiprint
- lda isr_done
lsr
bcc -
@@ -87,5 +130,5 @@ sysinfo_printloop:
+ plp
jsr restore_screen
lda #$00
sta @AVR_CMD
sta @MCU_CMD
rtl

View File

@@ -1,146 +1,95 @@
.text
#include "memmap.i65"
.byt "===HIPRINT==="
; input:
; print_count
; print_x
; print_y
; print_src
; print_bank
; print_pal
;
; output:
; print_done (# of chars printed)
; print_over (char after print_count)
hiprint:
php
sep #$20 : .as
lda print_count
sta print_count_tmp
stz print_over
rep #$30 : .xl : .al
stz print_done
lda print_x
and #$00ff
lsr
bcs print_bg1
ldx #!BG1_TILE_BUF ; for 2nd loop
phx
ldx #!BG2_TILE_BUF ; for 1st loop
phx
bra print_bg_cont
print_bg1
ldx #!BG2_TILE_BUF+2 ; for 2nd loop
phx
ldx #!BG1_TILE_BUF ; for 1st loop da whoop
phx
bra print_bg_cont
print_bg_cont
sta !print_temp
lda !print_y
and #$00ff
asl
asl
asl
asl
asl
clc
adc !print_temp
asl ; double the offset for WRAM addressing
tay ; zonday
plx
phy ; offset from tilemap start
stx !print_temp
clc
adc !print_temp
; we need to transfer to WRAM and from there to VRAM via DMA during VBLANK
; because VRAM can only be accessed during VBLANK and forced blanking.
sta $2181
sep #$20 : .as
lda #$7f ;we really only need bit 0. full bank given for clarity
sta $2183
print_loop
ldx !print_src
lda !print_bank
pha
plb
phx ; source addr
print_loop_inner
lda !0,x
bne +
jmp print_end2
+ asl
sta @$2180
lda @print_pal
asl
asl
adc #$00
ora #$20
sta @$2180
lda @print_done
inc
sta @print_done
inx
lda !0,x
beq print_loop2
inx
lda !0,x
beq print_loop2
lda @print_count_tmp
dec
dec
sta @print_count_tmp
beq print_loop2
bmi print_loop2
bra print_loop_inner
print_loop2
lda @print_count
dec
sta @print_count_tmp
beq print_end2
lda #$00
rep #$10 : .xl
ldx print_src
stx print_ptr
lda print_bank
sta print_ptr+2
phb
lda #$7e
pha
plb
rep #$30 : .al : .xl
ply ; source addr
iny
pla ; offset from tilemap start
plx ; other tilemap addr
stx !print_temp
lda print_pal
and #$00ff
xba
asl
asl
ora #$2000
sta print_temp
lda print_count
and #$00ff
beq hiprint_end
tay
lda print_x
and #$00ff
sta print_x
lda print_y
and #$00ff
asl
asl
asl
asl
asl
asl
clc
adc !print_temp ; tilemap+offset
sta $2181
tyx
adc print_x
and #$fffe
tax
lda print_x
lsr
bcs hiprint_bg1
hiprint_bg2
lda [print_ptr]
and #$00ff
beq hiprint_end
inc print_ptr
asl
ora print_temp
sta !BG2_TILE_BUF, x
dey
beq hiprint_end
hiprint_bg1
lda [print_ptr]
and #$00ff
beq hiprint_end
inc print_ptr
asl
ora print_temp
sta !BG1_TILE_BUF, x
inx
inx
dey
beq hiprint_end
bra hiprint_bg2
hiprint_end
plb
sep #$20 : .as
lda print_bank
pha
plb
print_loop2_inner
lda !0,x
bne +
jmp print_end
+ asl
sta @$2180
lda @print_pal
asl
asl
adc #$00
ora #$20
sta @$2180
lda @print_done
lda [print_ptr]
sta print_over
tya
sec
sbc print_count
eor #$ff
inc
sta @print_done
inx
lda !0,x
beq print_end
lda @print_count_tmp
dec
dec
sta @print_count_tmp
beq print_end
bmi print_end
inx
lda !0,x
beq print_end
bra print_loop2_inner
print_end2 ; clean up the stack (6 bytes)
ply
ply
ply
print_end
lda !0,x
sta @print_over
lda #$00
pha
plb
sta print_done
plp
rts
@@ -290,6 +239,7 @@ draw_window:
sta print_count
jsr hiprint
lda print_done
clc
adc print_x
sta print_x
lda #^window_tr

View File

@@ -499,6 +499,8 @@ time_dec_y1_normal
rts
gettime
php
sep #$20 : .as
lda #$0d
sta $2801
lda $2800
@@ -526,6 +528,7 @@ gettime
sta time_y10
lda $2800
sta time_y100
plp
rts
rendertime
@@ -677,31 +680,31 @@ is_leapyear_400th
settime
lda time_y100
sta @AVR_PARAM
sta @MCU_PARAM
lda time_y10
sta @AVR_PARAM+1
sta @MCU_PARAM+1
lda time_y1
sta @AVR_PARAM+2
sta @MCU_PARAM+2
lda time_mon
sta @AVR_PARAM+3
sta @MCU_PARAM+3
lda time_d10
sta @AVR_PARAM+4
sta @MCU_PARAM+4
lda time_d1
sta @AVR_PARAM+5
sta @MCU_PARAM+5
lda time_h10
sta @AVR_PARAM+6
sta @MCU_PARAM+6
lda time_h1
sta @AVR_PARAM+7
sta @MCU_PARAM+7
lda time_m10
sta @AVR_PARAM+8
sta @MCU_PARAM+8
lda time_m1
sta @AVR_PARAM+9
sta @MCU_PARAM+9
lda time_s10
sta @AVR_PARAM+10
sta @MCU_PARAM+10
lda time_s1
sta @AVR_PARAM+11
sta @MCU_PARAM+11
lda #$02 ; set clock
sta @AVR_CMD
sta @MCU_CMD
rts
printtime:

View File

@@ -75,7 +75,7 @@ ASRC = startup.S crc.S
# (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
OPT = s
# Debugging format.
DEBUG = dwarf-2
@@ -124,7 +124,8 @@ NM = $(ARCH)-nm
REMOVE = rm -f
COPY = cp
AWK = awk
RLE = ../utils/rle
BIN2H = utils/bin2h
#---------------- Compiler Options ----------------
# -g*: generate debugging information
@@ -197,7 +198,7 @@ ALL_ASFLAGS = -I. -x assembler-with-cpp $(ASFLAGS) $(CDEFS)
# Default target.
all: build
build: elf bin hex
build: elf bin hex cfgware.h
$(E) " SIZE $(TARGET).elf"
$(Q)$(ELFSIZE)|grep -v debug
cp $(TARGET).bin $(OBJDIR)/firmware.img
@@ -230,6 +231,13 @@ HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -A $(TARGET).elf
# Generate cfgware.h
cfgware.h: $(OBJDIR)/fpga_rle.bit
$(E) " BIN2H $@"
$(Q) $(BIN2H) $< $@
$(OBJDIR)/fpga_rle.bit: sd2sneslite.bit
$(E) " RLE $@"
$(Q) $(RLE) $< $@
# Generate autoconf.h from config
.PRECIOUS : $(OBJDIR)/autoconf.h
@@ -302,6 +310,7 @@ clean_list :
$(Q)$(REMOVE) $(TARGET).sym
$(Q)$(REMOVE) $(TARGET).lss
$(Q)$(REMOVE) $(OBJ)
$(Q)$(REMOVE) cfgware.h
$(Q)$(REMOVE) $(OBJDIR)/autoconf.h
$(Q)$(REMOVE) $(OBJDIR)/*.bin
$(Q)$(REMOVE) $(LST)

View File

@@ -17,6 +17,7 @@ b) Cortex M3 toolchain
- texinfo
- libmpfr-dev
- libgmp3-dev
- libmpc-dev
- gawk
- bison
- recode
@@ -25,6 +26,7 @@ b) Cortex M3 toolchain
- libexpat-dev
- make
- gcc
Package names may differ for your distribution.
Newer gccs complain when compiling binutils, so you may have to add
'--disable-werror' to the compiler options for binutils in the Makefile.
The Makefile will install immediately so make sure you can write to the

View File

@@ -55,7 +55,8 @@
//#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_BAUDRATE 921600
#define CONFIG_UART_BAUDRATE 115200
#define CONFIG_UART_DEADLOCKABLE
#define SSP_CLK_DIVISOR_FAST 2

View File

@@ -31,7 +31,7 @@
enum filestates { FILE_OK=0, FILE_ERR, FILE_EOF };
BYTE file_buf[512];
BYTE file_buf[512] __attribute__((aligned(4)));
FATFS fatfs;
FIL file_handle;
FRESULT file_res;

View File

@@ -189,7 +189,7 @@ FLASH_RES flash_file(uint8_t *filename) {
}
DBG_UART uart_putc('w');
if((res = iap_ram2flash(flash_addr, file_buf, 512)) != CMD_SUCCESS) {
DBG_BL printf("error %ld while writing to address %08lx (sector %d)\n", res, flash_addr, current_sec);
DBG_BL printf("error %ld while writing from %08lX to address %08lx (sector %d)\n", res, (uint32_t)file_buf, flash_addr, current_sec);
DBG_UART uart_putc('X');
return ERR_FLASH;
}

View File

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

View File

@@ -52,8 +52,12 @@ int main(void) {
clock_init();
// LPC_PINCON->PINSEL0 |= BV(20) | BV(21); /* MAT3.0 (FPGA clock) */
sdn_init();
for(i = 0; i < 20; i++) uart_putc('-');
uart_putc('\n');
DBG_BL printf("chksum=%08lx\n", *(uint32_t*)28);
DBG_BL printf("\n\nsd2snes mk.2 bootloader\nver.: " VER "\ncpu clock: %ld Hz\n", CONFIG_CPU_FREQUENCY);
/*DBG_BL*/ printf("\n\nsd2snes mk.2 bootloader\nver.: " VER "\ncpu clock: %ld Hz\n", CONFIG_CPU_FREQUENCY);
DBG_BL printf("PCONP=%lx\n", LPC_SC->PCONP);
/* setup timer (fpga clk) */
LPC_TIM3->CTCR=0;

View File

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

View File

@@ -119,7 +119,7 @@ void uart_init(void) {
/* set baud rate - no fractional stuff for now */
UART_REGS->LCR = BV(7) | 3; // always 8n1
div = 0x850004; // baud2divisor(CONFIG_UART_BAUDRATE);
div = 0xF80022; //0x850004; // baud2divisor(CONFIG_UART_BAUDRATE);
UART_REGS->DLL = div & 0xff;
UART_REGS->DLM = (div >> 8) & 0xff;

59
src/cfg.c Normal file
View File

@@ -0,0 +1,59 @@
#include "cfg.h"
#include "config.h"
#include "uart.h"
#include "fileops.h"
cfg_t CFG = {
.cfg_ver_maj = 1,
.cfg_ver_min = 0,
.last_game_valid = 0,
.vidmode_menu = VIDMODE_AUTO,
.vidmode_game = VIDMODE_AUTO,
.pair_mode_allowed = 0,
.bsx_use_systime = 0,
.bsx_time = 0x0619970301180530LL
};
int cfg_save() {
int err = 0;
file_open(CFG_FILE, FA_CREATE_ALWAYS | FA_WRITE);
if(file_writeblock(&CFG, 0, sizeof(CFG)) < sizeof(CFG)) {
err = file_res;
}
file_close();
return err;
}
int cfg_load() {
int err = 0;
file_open(CFG_FILE, FA_READ);
if(file_readblock(&CFG, 0, sizeof(CFG)) < sizeof(CFG)) {
err = file_res;
}
file_close();
return err;
}
int cfg_save_last_game(uint8_t *fn) {
int err = 0;
file_open(LAST_FILE, FA_CREATE_ALWAYS | FA_WRITE);
err = f_puts((const TCHAR*)fn, &file_handle);
file_close();
return err;
}
int cfg_get_last_game(uint8_t *fn) {
int err = 0;
file_open(LAST_FILE, FA_READ);
f_gets((TCHAR*)fn, 255, &file_handle);
file_close();
return err;
}
void cfg_set_last_game_valid(uint8_t valid) {
CFG.last_game_valid = valid;
}
uint8_t cfg_is_last_game_valid() {
return CFG.last_game_valid;
}

39
src/cfg.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef _CFG_H
#define _CFG_H
#include <stdint.h>
#define CFG_FILE ((const uint8_t*)"/sd2snes/sd2snes.cfg")
#define LAST_FILE ((const uint8_t*)"/sd2snes/lastgame.cfg")
typedef enum {
VIDMODE_AUTO = 0,
VIDMODE_60,
VIDMODE_50
} cfg_vidmode_t;
typedef struct _cfg_block {
uint8_t cfg_ver_maj;
uint8_t cfg_ver_min;
uint8_t last_game_valid;
uint8_t vidmode_menu;
uint8_t vidmode_game;
uint8_t pair_mode_allowed;
uint8_t bsx_use_systime;
uint64_t bsx_time;
} cfg_t;
int cfg_save(void);
int cfg_load(void);
int cfg_save_last_game(uint8_t *fn);
int cfg_get_last_game(uint8_t *fn);
cfg_vidmode_t cfg_get_vidmode_menu(void);
cfg_vidmode_t cfg_get_vidmode_game(void);
void cfg_set_last_game_valid(uint8_t);
uint8_t cfg_is_last_game_valid(void);
uint8_t cfg_is_pair_mode_allowed(void);
#endif

File diff suppressed because it is too large Load Diff

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\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 };
"cd\0reset\0sreset\0dir\0ls\0test\0exit\0loadrom\0loadraw\0saveraw\0put\0rm\0mkdir\0d4\0vmode\0mapper\0settime\0time\0setfeature\0hexdump\0w8\0w16\0memset\0";
enum { CMD_CD = 0, CMD_RESET, CMD_SRESET, CMD_DIR, CMD_LS, CMD_TEST, CMD_EXIT, CMD_LOADROM, CMD_LOADRAW, CMD_SAVERAW, CMD_PUT, CMD_RM, CMD_MKDIR, CMD_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME, CMD_SETFEATURE, CMD_HEXDUMP, CMD_W8, CMD_W16, CMD_MEMSET };
/* ------------------------------------------------------------------------- */
/* Parse functions */
@@ -104,11 +104,11 @@ static int32_t parse_unsigned(uint32_t lower, uint32_t upper, uint8_t base) {
/* 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;
unsigned char *cur, *ptr;
unsigned char c;
i = 0;
ptr = wordlist;
ptr = (unsigned char *)wordlist;
// Command list on "?"
if (strlen(curchar) == 1 && *curchar == '?') {
@@ -128,7 +128,7 @@ static int8_t parse_wordlist(char *wordlist) {
}
while (1) {
cur = curchar;
cur = (unsigned char *)curchar;
matched = 1;
c = *ptr;
do {
@@ -138,9 +138,9 @@ static int8_t parse_wordlist(char *wordlist) {
return -1;
}
if (tolower(c) != tolower(*cur)) {
if (tolower((int)c) != tolower((int)*cur)) {
// Check for end-of-word
if (cur != curchar && (*cur == ' ' || *cur == 0)) {
if (cur != (unsigned char*)curchar && (*cur == ' ' || *cur == 0)) {
// Partial match found, return that
break;
} else {
@@ -156,7 +156,7 @@ static int8_t parse_wordlist(char *wordlist) {
if (matched) {
char *tmp = curchar;
curchar = cur;
curchar = (char *)cur;
// Return match only if whitespace or end-of-string follows
// (avoids mismatching partial words)
if (skip_spaces()) {
@@ -269,7 +269,7 @@ static void cmd_show_directory(void) {
strlwr((char *)name);
}
printf("%s",name);
printf("%s [%s] (%ld)",finfo.lfname, finfo.fname, finfo.fsize);
/* Directory indicator (Unix-style) */
if (finfo.fattrib & AM_DIR)
@@ -294,7 +294,8 @@ static void cmd_loadraw(void) {
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);
if(address != -1 && length != -1)
save_sram((uint8_t*)curchar, length, address);
}
static void cmd_d4(void) {
@@ -348,6 +349,11 @@ void cmd_rm(void) {
if(res) printf("Error %d removing %s\n", res, curchar);
}
void cmd_mkdir(void) {
FRESULT res = f_mkdir(curchar);
if(res) printf("Error %d creating directory %s\n", res, curchar);
}
void cmd_mapper(void) {
int32_t mapper;
mapper = parse_unsigned(0,7,10);
@@ -361,9 +367,7 @@ void cmd_sreset(void) {
resetstate = parse_unsigned(0,1,10);
snes_reset(resetstate);
} else {
snes_reset(1);
delay_ms(20);
snes_reset(0);
snes_reset_pulse();
}
}
void cmd_settime(void) {
@@ -416,6 +420,13 @@ void cmd_w16(void) {
sram_writeshort(val, offset);
}
void cmd_memset(void) {
uint32_t offset = parse_unsigned(0, 16777215, 16);
uint32_t len = parse_unsigned(0, 16777216, 16);
uint8_t val = parse_unsigned(0, 255, 16);
sram_memset(offset, len, val);
}
/* ------------------------------------------------------------------------- */
/* CLI interface functions */
/* ------------------------------------------------------------------------- */
@@ -498,7 +509,7 @@ void cli_loop(void) {
cmd_show_directory();
break;
case CMD_RESUME:
case CMD_EXIT:
return;
break;
@@ -518,6 +529,10 @@ void cli_loop(void) {
cmd_rm();
break;
case CMD_MKDIR:
cmd_mkdir();
break;
case CMD_D4:
cmd_d4();
break;
@@ -561,7 +576,11 @@ void cli_loop(void) {
case CMD_W16:
cmd_w16();
break;
}
case CMD_MEMSET:
cmd_memset();
break;
}
}
}

View File

@@ -27,7 +27,7 @@ void clock_init() {
-> FPGA freq = 11289473.7Hz
First, disable and disconnect PLL0.
*/
// clock_disconnect();
clock_disconnect();
/* PLL is disabled and disconnected. setup PCLK NOW as it cannot be changed
reliably with PLL0 connected.
@@ -48,12 +48,19 @@ void clock_init() {
*/
enableMainOsc();
setClkSrc(CLKSRC_MAINOSC);
// XXX setPLL0MultPrediv(429, 19);
// XXX setPLL0MultPrediv(23, 2);
setPLL0MultPrediv(12, 1);
setPLL0MultPrediv(22, 1);
enablePLL0();
setCCLKDiv(3);
setCCLKDiv(6);
connectPLL0();
/* configure PLL1 for USB operation */
disconnectPLL1();
disablePLL1();
LPC_SC->PLL1CFG = 0x23;
enablePLL1();
connectPLL1();
}
void setFlashAccessTime(uint8_t clocks) {
@@ -76,7 +83,7 @@ void disablePLL0() {
}
void connectPLL0() {
while(!(LPC_SC->PLL0STAT&PLOCK0));
while(!(LPC_SC->PLL0STAT & PLOCK0));
LPC_SC->PLL0CON |= PLLC0;
PLL0feed();
}
@@ -86,6 +93,32 @@ void disconnectPLL0() {
PLL0feed();
}
void setPLL1MultPrediv(uint16_t mult, uint8_t prediv) {
LPC_SC->PLL1CFG=PLL_MULT(mult) | PLL_PREDIV(prediv);
PLL1feed();
}
void enablePLL1() {
LPC_SC->PLL1CON |= PLLE1;
PLL1feed();
}
void disablePLL1() {
LPC_SC->PLL1CON &= ~PLLE1;
PLL1feed();
}
void connectPLL1() {
while(!(LPC_SC->PLL1STAT & PLOCK1));
LPC_SC->PLL1CON |= PLLC1;
PLL1feed();
}
void disconnectPLL1() {
LPC_SC->PLL1CON &= ~PLLC1;
PLL1feed();
}
void setCCLKDiv(uint8_t div) {
LPC_SC->CCLKCFG=CCLK_DIV(div);
}
@@ -104,6 +137,11 @@ void PLL0feed() {
LPC_SC->PLL0FEED=0x55;
}
void PLL1feed() {
LPC_SC->PLL1FEED=0xaa;
LPC_SC->PLL1FEED=0x55;
}
void setClkSrc(uint8_t src) {
LPC_SC->CLKSRCSEL=src;
}

View File

@@ -8,6 +8,9 @@
#define PLLE0 (1<<0)
#define PLLC0 (1<<1)
#define PLOCK0 (1<<26)
#define PLLE1 (1<<0)
#define PLLC1 (1<<1)
#define PLOCK1 (1<<10)
#define OSCEN (1<<5)
#define OSCSTAT (1<<6)
#define FLASHTIM(x) (((x-1)<<12)|0x3A)
@@ -56,14 +59,18 @@ 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 PLL0feed(void);
void setPLL1MultPrediv(uint16_t mult, uint8_t prediv);
void enablePLL1(void);
void disablePLL1(void);
void connectPLL1(void);
void disconnectPLL1(void);
void PLL1feed(void);
void setCCLKDiv(uint8_t div);
@@ -71,9 +78,5 @@ void enableMainOsc(void);
void disableMainOsc(void);
void PLL0feed(void);
void setClkSrc(uint8_t src);
#endif

View File

@@ -1,4 +1,4 @@
CONFIG_VERSION="0.1.3"
CONFIG_VERSION="0.1.5"
#FWVER=00010300
CONFIG_FWVER=66304
CONFIG_FWVER=0x00010500
CONFIG_MCU_FOSC=12000000

View File

@@ -35,18 +35,15 @@
#define CONFIG_UART_NUM 3
// #define CONFIG_CPU_FREQUENCY 90315789
#define CONFIG_CPU_FREQUENCY 96000000
#define CONFIG_CPU_FREQUENCY 88000000
//#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_BAUDRATE 921600
#define CONFIG_UART_BAUDRATE 115200
#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 SSP_CLK_DIVISOR 2
#define SNES_RESET_REG LPC_GPIO1
#define SNES_RESET_BIT 26
@@ -67,7 +64,11 @@
#define FPGA_MCU_RDY_BIT 9
#define QSORT_MAXELEM 2048
#define SORT_STRLEN 256
#define CLTBL_SIZE 100
#define DIR_FILE_MAX 16380
#define SSP_REGS LPC_SSP0
#define SSP_PCLKREG PCLKSEL1
// 1: PCLKSEL0
@@ -95,4 +96,7 @@
#define SD_DAT (LPC_GPIO2->FIOPIN0)
#define USB_CONNREG LPC_GPIO4
#define USB_CONNBIT 28
#endif

View File

@@ -55,7 +55,7 @@ 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
DRESULT disk_ioctl (BYTE, BYTE, void*);
void disk_init(void);

View File

@@ -3644,6 +3644,7 @@ TCHAR* f_gets (
*p++ = c;
n++;
if (c == '\n') break; /* Break on EOL */
if (c == 0) break; /* Break on NUL */
}
*p = 0;
return n ? buff : 0; /* When no data read (eof or error), return with error. */

View File

@@ -31,7 +31,7 @@
#include "ff.h"
#include "smc.h"
#include "fileops.h"
#include "crc32.h"
#include "crc.h"
#include "memory.h"
#include "led.h"
#include "sort.h"
@@ -60,15 +60,16 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
uint8_t len;
TCHAR* fn;
static unsigned char depth = 0;
static uint32_t crc;
static uint32_t crc, fncrc;
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;
/* static uint8_t was_empty = 0;*/
static uint16_t num_files_total = 0;
static uint16_t num_dirs_total = 0;
uint32_t dir_tgt;
uint32_t switched_dir_tgt = 0;
uint16_t numentries;
uint32_t dirsize;
uint8_t pass = 0;
@@ -76,6 +77,7 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
char *size_units[3] = {" ", "k", "M"};
uint32_t entry_fsize;
uint8_t entry_unit_idx;
uint16_t entrycnt;
dir_tgt = this_dir_tgt;
if(depth==0) {
@@ -91,10 +93,18 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
fno.lfsize = 255;
fno.lfname = (TCHAR*)file_lfn;
numentries=0;
for(pass = 0; pass < 2; pass++) {
for(pass = 0; pass < (mkdb ? 2 : 1); pass++) {
if(pass) {
num_dirs_total++;
dirsize = 4*(numentries);
if(((next_subdir_tgt + dirsize + 8) & 0xff0000) > (next_subdir_tgt & 0xff0000)) {
printf("switchdir! old=%lX ", next_subdir_tgt + dirsize + 4);
next_subdir_tgt &= 0xffff0000;
next_subdir_tgt += 0x00010004;
printf("new=%lx\n", next_subdir_tgt);
dir_tgt &= 0xffff0000;
dir_tgt += 0x00010004;
}
switched_dir_tgt = dir_tgt;
next_subdir_tgt += dirsize + 4;
if(parent_tgt) next_subdir_tgt += 4;
if(next_subdir_tgt > dir_end) {
@@ -102,6 +112,7 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
}
DBG_FS printf("path=%s depth=%d ptr=%lx entries=%d parent=%lx next subdir @%lx\n", path, depth, db_tgt, numentries, parent_tgt, next_subdir_tgt);
if(mkdb) {
num_dirs_total++;
// printf("d=%d Saving %lx to Address %lx [end]\n", depth, 0L, next_subdir_tgt - 4);
sram_writelong(0L, next_subdir_tgt - 4);
}
@@ -130,27 +141,30 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
dir_tgt += 4;
}
len = strlen((char*)path);
for (;;) {
/* scan at most DIR_FILE_MAX entries per directory */
for(entrycnt=0; entrycnt < DIR_FILE_MAX; entrycnt++) {
// toggle_read_led();
res = f_readdir(&dir, &fno);
if (res != FR_OK || fno.fname[0] == 0) {
if(pass) {
if(!numentries) was_empty=1;
/* 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 ((*fn == '.') || !(strncasecmp(fn, SYS_DIR_NAME, strlen(SYS_DIR_NAME)+1))) continue;
if (fno.fattrib & AM_DIR) {
depth++;
if(depth < FS_MAX_DEPTH) {
numentries++;
if(pass) {
if(pass && mkdb) {
path[len]='/';
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
uint16_t pathlen = 0;
uint32_t old_db_tgt = 0;
if(mkdb) {
uint16_t pathlen = strlen(path);
// printf("d=%d Saving %lx to Address %lx [dir]\n", depth, db_tgt, dir_tgt);
pathlen = strlen(path);
DBG_FS printf("d=%d Saving %lx to Address %lx [dir]\n", depth, db_tgt, dir_tgt);
/* save element:
- path name
- pointer to sub dir structure */
@@ -160,22 +174,31 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
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);
- pointer to sub dir structure
moved below */
old_db_tgt = db_tgt;
db_tgt += sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2;
}
parent_tgt = this_dir_tgt;
scan_dir(path, &fno, mkdb, next_subdir_tgt);
/* scan subdir before writing current dir element to account for bank switches */
uint32_t corrected_subdir_tgt = scan_dir(path, &fno, mkdb, next_subdir_tgt);
if(mkdb) {
DBG_FS printf(" Saving dir descriptor to %lx tgt=%lx, path=%s\n", old_db_tgt, corrected_subdir_tgt, path);
sram_writelong((corrected_subdir_tgt-SRAM_MENU_ADDR), old_db_tgt);
sram_writebyte(len+1, old_db_tgt+sizeof(next_subdir_tgt));
sram_writeblock(path, old_db_tgt+sizeof(next_subdir_tgt)+sizeof(len), pathlen);
sram_writeblock("/\0", old_db_tgt + sizeof(next_subdir_tgt) + sizeof(len) + pathlen, 2);
}
dir_tgt += 4;
was_empty = 0;
/* was_empty = 0;*/
} else if(!mkdb) {
path[len]='/';
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
scan_dir(path, &fno, mkdb, next_subdir_tgt);
}
}
depth--;
@@ -183,10 +206,10 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
} else {
SNES_FTYPE type = determine_filetype((char*)fn);
if(type != TYPE_UNKNOWN) {
num_files_total++;
numentries++;
if(pass) {
if(mkdb) {
num_files_total++;
/* snes_romprops_t romprops; */
path[len]='/';
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
@@ -194,13 +217,7 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
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(); */
case TYPE_SPC:
/* 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)) {
@@ -234,19 +251,19 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
default:
break;
}
path[len]=0;
path[len] = 0;
/* printf("%s ", path);
_delay_ms(30); */
}
} else {
TCHAR* fn2 = fn;
fncrc = 0;
while(*fn2 != 0) {
crc += crc32_update(crc, *((unsigned char*)fn2++));
fncrc += crc_xmodem_update(fncrc, *((unsigned char*)fn2++));
}
crc += fncrc;
}
}
/* printf("%s/%s\n", path, fn);
_delay_ms(50); */
}
}
} else uart_putc(0x30+res);
@@ -256,7 +273,9 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
sram_writelong(dir_end, SRAM_DB_ADDR+8);
sram_writeshort(num_files_total, SRAM_DB_ADDR+12);
sram_writeshort(num_dirs_total, SRAM_DB_ADDR+14);
return crc;
if(depth==0) return crc;
else return switched_dir_tgt;
return was_empty; // tricky!
}
@@ -271,18 +290,14 @@ SNES_FTYPE determine_filetype(char* filename) {
) {
return TYPE_SMC;
}
if( (!strcasecmp(ext+1, "IPS"))
/* 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;
}*/
if(!strcasecmp(ext+1, "SPC")) {
return TYPE_SPC;
}
return TYPE_UNKNOWN;
}

View File

@@ -36,7 +36,7 @@
#include "ff.h"
#define FS_MAX_DEPTH (10)
#define SYS_DIR_NAME ((const uint8_t*)"sd2snes")
#define SYS_DIR_NAME ((const char*)"sd2snes")
typedef enum {
TYPE_UNKNOWN = 0, /* 0 */
TYPE_SMC, /* 1 */

View File

@@ -98,37 +98,43 @@ void fpga_pgm(uint8_t* filename) {
uint8_t data;
int i;
tick_t timeout;
/* open configware file */
file_open(filename, FA_READ);
if(file_res) {
uart_putc('?');
uart_putc(0x30+file_res);
return;
}
do {
i=0;
timeout = getticks() + 100;
timeout = getticks() + 1;
fpga_set_prog_b(0);
if(BITBAND(PROGBREG->FIOPIN, PROGBBIT)) {
printf("PROGB is stuck high!\n");
led_panic();
}
while(BITBAND(PROGBREG->FIOPIN, PROGBBIT)) {
if(getticks() > timeout) {
printf("PROGB is stuck high!\n");
led_panic(LED_PANIC_FPGA_PROGB_STUCK);
}
}
timeout = getticks() + 100;
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();
led_panic(LED_PANIC_FPGA_NO_INITB);
}
};
if(fpga_get_done()) {
printf("DONE is stuck high!\n");
led_panic();
timeout = getticks() + 100;
while(fpga_get_done()) {
if(getticks() > timeout) {
printf("DONE is stuck high!\n");
led_panic(LED_PANIC_FPGA_DONE_STUCK);
}
}
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 (;;) {
@@ -144,7 +150,7 @@ if(BITBAND(PROGBREG->FIOPIN, PROGBBIT)) {
} while (!fpga_get_done() && retries--);
if(!fpga_get_done()) {
printf("FPGA failed to configure after %d tries.\n", MAXRETRIES);
led_panic();
led_panic(LED_PANIC_FPGA_NOCONF);
}
printf("FPGA configured\n");
fpga_postinit();
@@ -165,12 +171,15 @@ void fpga_rompgm() {
while(!fpga_get_initb()){
if(getticks() > timeout) {
printf("no response from FPGA trying to initiate configuration!\n");
led_panic();
led_panic(LED_PANIC_FPGA_NO_INITB);
}
};
if(fpga_get_done()) {
printf("DONE is stuck high!\n");
led_panic();
timeout = getticks() + 100;
while(fpga_get_done()) {
if(getticks() > timeout) {
printf("DONE is stuck high!\n");
led_panic(LED_PANIC_FPGA_DONE_STUCK);
}
}
LPC_GPIO2->FIOMASK1 = ~(BV(0));
uart_putc('p');
@@ -190,7 +199,7 @@ void fpga_rompgm() {
} while (!fpga_get_done() && retries--);
if(!fpga_get_done()) {
printf("FPGA failed to configure after %d tries.\n", MAXRETRIES);
led_panic();
led_panic(LED_PANIC_FPGA_NOCONF);
}
printf("FPGA configured\n");
fpga_postinit();

View File

@@ -1,6 +1,6 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Copyright (C) 2009-2012 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.
@@ -143,13 +143,13 @@
#include "sdnative.h"
void fpga_spi_init(void) {
spi_init(SPI_SPEED_FAST);
spi_init();
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(FPGA_CMD_SETADDR | FPGA_TGT_MSUBUF);
FPGA_TX_BYTE((address>>8)&0xff);
FPGA_TX_BYTE((address)&0xff);
FPGA_DESELECT();
@@ -157,7 +157,7 @@ void set_msu_addr(uint16_t address) {
void set_dac_addr(uint16_t address) {
FPGA_SELECT();
FPGA_TX_BYTE(0x01);
FPGA_TX_BYTE(FPGA_CMD_SETADDR | FPGA_TGT_DACBUF);
FPGA_TX_BYTE((address>>8)&0xff);
FPGA_TX_BYTE((address)&0xff);
FPGA_DESELECT();
@@ -165,7 +165,7 @@ void set_dac_addr(uint16_t address) {
void set_mcu_addr(uint32_t address) {
FPGA_SELECT();
FPGA_TX_BYTE(0x00);
FPGA_TX_BYTE(FPGA_CMD_SETADDR | FPGA_TGT_MEM);
FPGA_TX_BYTE((address>>16)&0xff);
FPGA_TX_BYTE((address>>8)&0xff);
FPGA_TX_BYTE((address)&0xff);
@@ -174,7 +174,7 @@ void set_mcu_addr(uint32_t address) {
void set_saveram_mask(uint32_t mask) {
FPGA_SELECT();
FPGA_TX_BYTE(0x20);
FPGA_TX_BYTE(FPGA_CMD_SETRAMMASK);
FPGA_TX_BYTE((mask>>16)&0xff);
FPGA_TX_BYTE((mask>>8)&0xff);
FPGA_TX_BYTE((mask)&0xff);
@@ -183,7 +183,7 @@ void set_saveram_mask(uint32_t mask) {
void set_rom_mask(uint32_t mask) {
FPGA_SELECT();
FPGA_TX_BYTE(0x10);
FPGA_TX_BYTE(FPGA_CMD_SETROMMASK);
FPGA_TX_BYTE((mask>>16)&0xff);
FPGA_TX_BYTE((mask>>8)&0xff);
FPGA_TX_BYTE((mask)&0xff);
@@ -192,14 +192,13 @@ void set_rom_mask(uint32_t mask) {
void set_mapper(uint8_t val) {
FPGA_SELECT();
FPGA_TX_BYTE(0x30 | (val & 0x0f));
FPGA_TX_BYTE(FPGA_CMD_SETMAPPER(val));
FPGA_DESELECT();
}
uint8_t fpga_test() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF0); /* TEST */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(FPGA_CMD_TEST);
uint8_t result = FPGA_RX_BYTE();
FPGA_DESELECT();
return result;
@@ -207,8 +206,7 @@ uint8_t fpga_test() {
uint16_t fpga_status() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF1); /* STATUS */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(FPGA_CMD_GETSTATUS);
uint16_t result = (FPGA_RX_BYTE()) << 8;
result |= FPGA_RX_BYTE();
FPGA_DESELECT();
@@ -216,65 +214,50 @@ uint16_t fpga_status() {
}
void fpga_set_sddma_range(uint16_t start, uint16_t end) {
printf("%s %08X -> %08X\n", __func__, start, end);
FPGA_SELECT();
FPGA_TX_BYTE(0x60); /* DMA_RANGE */
FPGA_TX_BYTE(FPGA_CMD_SDDMA_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(FPGA_CMD_SDDMA | (tgt & 3) | (partial ? FPGA_SDDMA_PARTIAL : 0));
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 */
FPGA_TX_BYTE(FPGA_CMD_GETSTATUS);
DBG_SD printf("FPGA DMA request sent, wait for completion...");
while((status=FPGA_RX_BYTE()) & 0x80) {
while(FPGA_RX_BYTE() & 0x80) {
FPGA_RX_BYTE(); /* eat the 2nd status byte */
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(FPGA_CMD_DACPLAY);
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_DESELECT();
}
void dac_pause() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe1);
FPGA_TX_BYTE(FPGA_CMD_DACPAUSE);
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_DESELECT();
}
void dac_reset() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe3);
FPGA_TX_BYTE(FPGA_CMD_DACRESETPTR);
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_DESELECT();
@@ -282,7 +265,7 @@ void dac_reset() {
void msu_reset(uint16_t address) {
FPGA_SELECT();
FPGA_TX_BYTE(0xe4);
FPGA_TX_BYTE(FPGA_CMD_MSUSETPTR);
FPGA_TX_BYTE((address>>8) & 0xff); /* address hi */
FPGA_TX_BYTE(address & 0xff); /* address lo */
FPGA_TX_BYTE(0x00); /* latch reset */
@@ -292,26 +275,16 @@ void msu_reset(uint16_t address) {
void set_msu_status(uint8_t set, uint8_t reset) {
FPGA_SELECT();
FPGA_TX_BYTE(0xe0);
FPGA_TX_BYTE(FPGA_CMD_MSUSETBITS);
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 */
FPGA_TX_BYTE(FPGA_CMD_MSUGETTRACK);
uint16_t result = (FPGA_RX_BYTE()) << 8;
result |= FPGA_RX_BYTE();
FPGA_DESELECT();
@@ -320,8 +293,7 @@ uint16_t get_msu_track() {
uint32_t get_msu_offset() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF2); /* MSU_OFFSET */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(FPGA_CMD_MSUGETADDR);
uint32_t result = (FPGA_RX_BYTE()) << 24;
result |= (FPGA_RX_BYTE()) << 16;
result |= (FPGA_RX_BYTE()) << 8;
@@ -332,9 +304,8 @@ uint32_t get_msu_offset() {
uint32_t get_snes_sysclk() {
FPGA_SELECT();
FPGA_TX_BYTE(0xFE); /* GET_SYSCLK */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(FPGA_CMD_GETSYSCLK);
FPGA_TX_BYTE(0x00); /* dummy (copy current sysclk count to register) */
uint32_t result = (FPGA_RX_BYTE()) << 24;
result |= (FPGA_RX_BYTE()) << 16;
result |= (FPGA_RX_BYTE()) << 8;
@@ -345,7 +316,7 @@ uint32_t get_snes_sysclk() {
void set_bsx_regs(uint8_t set, uint8_t reset) {
FPGA_SELECT();
FPGA_TX_BYTE(0xe6);
FPGA_TX_BYTE(FPGA_CMD_BSXSETBITS);
FPGA_TX_BYTE(set);
FPGA_TX_BYTE(reset);
FPGA_TX_BYTE(0x00); /* latch reset */
@@ -354,7 +325,7 @@ void set_bsx_regs(uint8_t set, uint8_t reset) {
void set_fpga_time(uint64_t time) {
FPGA_SELECT();
FPGA_TX_BYTE(0xe5);
FPGA_TX_BYTE(FPGA_CMD_RTCSET);
FPGA_TX_BYTE((time >> 48) & 0xff);
FPGA_TX_BYTE((time >> 40) & 0xff);
FPGA_TX_BYTE((time >> 32) & 0xff);
@@ -368,7 +339,7 @@ void set_fpga_time(uint64_t time) {
void fpga_reset_srtc_state() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe7);
FPGA_TX_BYTE(FPGA_CMD_SRTCRESET);
FPGA_TX_BYTE(0x00);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
@@ -376,7 +347,7 @@ void fpga_reset_srtc_state() {
void fpga_reset_dspx_addr() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe8);
FPGA_TX_BYTE(FPGA_CMD_DSPRESETPTR);
FPGA_TX_BYTE(0x00);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
@@ -384,7 +355,7 @@ void fpga_reset_dspx_addr() {
void fpga_write_dspx_pgm(uint32_t data) {
FPGA_SELECT();
FPGA_TX_BYTE(0xe9);
FPGA_TX_BYTE(FPGA_CMD_DSPWRITEPGM);
FPGA_TX_BYTE((data>>16)&0xff);
FPGA_TX_BYTE((data>>8)&0xff);
FPGA_TX_BYTE((data)&0xff);
@@ -395,7 +366,7 @@ void fpga_write_dspx_pgm(uint32_t data) {
void fpga_write_dspx_dat(uint16_t data) {
FPGA_SELECT();
FPGA_TX_BYTE(0xea);
FPGA_TX_BYTE(FPGA_CMD_DSPWRITEDAT);
FPGA_TX_BYTE((data>>8)&0xff);
FPGA_TX_BYTE((data)&0xff);
FPGA_TX_BYTE(0x00);
@@ -405,7 +376,7 @@ void fpga_write_dspx_dat(uint16_t data) {
void fpga_dspx_reset(uint8_t reset) {
FPGA_SELECT();
FPGA_TX_BYTE(reset ? 0xeb : 0xec);
FPGA_TX_BYTE(reset ? FPGA_CMD_DSPRESET : FPGA_CMD_DSPUNRESET);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
@@ -413,7 +384,7 @@ void fpga_dspx_reset(uint8_t reset) {
void fpga_set_features(uint8_t feat) {
printf("set features: %02x\n", feat);
FPGA_SELECT();
FPGA_TX_BYTE(0xed);
FPGA_TX_BYTE(FPGA_CMD_SETFEATURE);
FPGA_TX_BYTE(feat);
FPGA_DESELECT();
}
@@ -421,7 +392,7 @@ void fpga_set_features(uint8_t feat) {
void fpga_set_213f(uint8_t data) {
printf("set 213f: %d\n", data);
FPGA_SELECT();
FPGA_TX_BYTE(0xee);
FPGA_TX_BYTE(FPGA_CMD_SET213F);
FPGA_TX_BYTE(data);
FPGA_DESELECT();
}

View File

@@ -47,9 +47,6 @@
#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_213F (1 << 4)
#define FEAT_MSU1 (1 << 3)
#define FEAT_SRTC (1 << 2)
@@ -60,6 +57,44 @@
#define FPGA_WAIT_RDY() do {while(BITBAND(SSP_REGS->SR, SSP_BSY)); while(!BITBAND(FPGA_MCU_RDY_REG->FIOPIN, FPGA_MCU_RDY_BIT));} while (0)
/* command parameters */
#define FPGA_MEM_AUTOINC (0x8)
#define FPGA_SDDMA_PARTIAL (0x4)
#define FPGA_TGT_MEM (0x0)
#define FPGA_TGT_DACBUF (0x1)
#define FPGA_TGT_MSUBUF (0x2)
/* commands */
#define FPGA_CMD_SETADDR (0x00)
#define FPGA_CMD_SETROMMASK (0x10)
#define FPGA_CMD_SETRAMMASK (0x20)
#define FPGA_CMD_SETMAPPER(x) (0x30 | (x & 15))
#define FPGA_CMD_SDDMA (0x40)
#define FPGA_CMD_SDDMA_RANGE (0x60)
#define FPGA_CMD_READMEM (0x80)
#define FPGA_CMD_WRITEMEM (0x90)
#define FPGA_CMD_MSUSETBITS (0xe0)
#define FPGA_CMD_DACPAUSE (0xe1)
#define FPGA_CMD_DACPLAY (0xe2)
#define FPGA_CMD_DACRESETPTR (0xe3)
#define FPGA_CMD_MSUSETPTR (0xe4)
#define FPGA_CMD_RTCSET (0xe5)
#define FPGA_CMD_BSXSETBITS (0xe6)
#define FPGA_CMD_SRTCRESET (0xe7)
#define FPGA_CMD_DSPRESETPTR (0xe8)
#define FPGA_CMD_DSPWRITEPGM (0xe9)
#define FPGA_CMD_DSPWRITEDAT (0xea)
#define FPGA_CMD_DSPRESET (0xeb)
#define FPGA_CMD_DSPUNRESET (0xec)
#define FPGA_CMD_SETFEATURE (0xed)
#define FPGA_CMD_SET213F (0xee)
#define FPGA_CMD_TEST (0xf0)
#define FPGA_CMD_GETSTATUS (0xf1)
#define FPGA_CMD_MSUGETADDR (0xf2)
#define FPGA_CMD_MSUGETTRACK (0xf3)
#define FPGA_CMD_GETSYSCLK (0xfe)
#define FPGA_CMD_ECHO (0xff)
void fpga_spi_init(void);
uint8_t fpga_test(void);
uint16_t fpga_status(void);
@@ -68,7 +103,6 @@ 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);
@@ -80,7 +114,6 @@ 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);

View File

@@ -85,12 +85,12 @@ void toggle_write_led() {
writeled(~led_writeledstate);
}
void led_panic() {
void led_panic(uint8_t led_states) {
led_std();
while(1) {
rdyled(1);
readled(1);
writeled(1);
rdyled((led_states >> 2) & 1);
readled((led_states >> 1) & 1);
writeled(led_states & 1);
delay_ms(100);
rdyled(0);
readled(0);

View File

@@ -3,6 +3,12 @@
#ifndef _LED_H
#define _LED_H
#define LED_PANIC_FPGA_PROGB_STUCK (1)
#define LED_PANIC_FPGA_NO_INITB (2)
#define LED_PANIC_FPGA_DONE_STUCK (3)
#define LED_PANIC_FPGA_NOCONF (4)
#define LED_PANIC_FPGA_DEAD (5)
void readbright(uint8_t bright);
void writebright(uint8_t bright);
void rdybright(uint8_t bright);
@@ -13,7 +19,7 @@ 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_panic(uint8_t led_states);
void led_pwm(void);
void led_std(void);
void led_init(void);

View File

@@ -26,9 +26,9 @@ if { [info exists CPUTAPID ] } {
}
#delays on reset lines
#if your OpenOCD version rejects "jtag_nsrst_delay" replace it with:
#adapter_nsrst_delay 200
jtag_nsrst_delay 200
#if your OpenOCD version rejects "adapter_nsrst_delay" replace it with:
#jtag_nsrst_delay 200
adapter_nsrst_delay 200
jtag_ntrst_delay 200
# LPC2000 & LPC1700 -> SRST causes TRST
@@ -39,7 +39,7 @@ 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
target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME -event reset-init 0
# LPC1754 has 16kB of SRAM In the ARMv7-M "Code" area (at 0x10000000)
# and 16K more on AHB, in the ARMv7-M "SRAM" area, (at 0x2007c000).
@@ -56,7 +56,7 @@ flash bank $_FLASHNAME lpc2000 0x0 0x20000 0 0 $_TARGETNAME \
# 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
adapter_khz 1000
$_TARGETNAME configure -event reset-init {
# Do not remap 0x0000-0x0020 to anything but the flash (i.e. select

View File

@@ -48,12 +48,14 @@ extern volatile int reset_changed;
extern volatile cfg_t CFG;
enum system_states {
enum system_states
{
SYS_RTC_STATUS = 0,
SYS_LAST_STATUS = 1
};
int main(void) {
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;
@@ -88,7 +90,9 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
file_init();
cic_init(0);
/* setup timer (fpga clk) */
LPC_TIM3->TCR=2;
LPC_TIM3->CTCR=0;
LPC_TIM3->PR=0;
LPC_TIM3->EMR=EMC0TOGGLE;
LPC_TIM3->MCR=MR0R;
LPC_TIM3->MR0=1;
@@ -119,17 +123,21 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
/* some sanity checks */
uint8_t card_go = 0;
while(!card_go) {
if(disk_status(0) & (STA_NOINIT|STA_NODISK)) {
snes_bootprint(" No SD Card found! \0");
while(disk_status(0) & (STA_NOINIT|STA_NODISK));
delay_ms(200);
if(disk_status(0) & (STA_NOINIT|STA_NODISK))
{
snes_bootprint(" No SD Card found! \0");
while(disk_status(0) & (STA_NOINIT|STA_NODISK));
delay_ms(200);
}
file_open((uint8_t*)"/sd2snes/menu.bin", FA_READ);
if(file_status != FILE_OK) {
snes_bootprint(" /sd2snes/menu.bin not found! \0");
while(disk_status(0) == RES_OK);
} else {
card_go = 1;
if(file_status != FILE_OK)
{
snes_bootprint(" /sd2snes/menu.bin not found! \0");
while(disk_status(0) == RES_OK);
}
else
{
card_go = 1;
}
file_close();
}
@@ -179,25 +187,27 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
snes_bootprint(" saving database ... \0");
save_sram((uint8_t*)"/sd2snes/sd2snes.db", endaddr-SRAM_DB_ADDR, SRAM_DB_ADDR);
save_sram((uint8_t*)"/sd2snes/sd2snes.dir", direndaddr-(SRAM_DIR_ADDR), SRAM_DIR_ADDR);
fpga_pgm((uint8_t*)"/sd2snes/fpga_base.bit");
printf("done\n");
} else {
printf("saved dir id = %lx\n", saved_dir_id);
printf("different card, consistent db, loading db...\n");
load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
fpga_pgm((uint8_t*)"/sd2snes/fpga_base.bit");
load_sram_offload((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
load_sram_offload((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
}
sram_writelong(curr_dir_id, SRAM_DIRID);
sram_writelong(0x12345678, SRAM_SCRATCHPAD);
} else {
snes_bootprint(" same card, loading db... \0");
printf("same card, loading db...\n");
load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
fpga_pgm((uint8_t*)"/sd2snes/fpga_base.bit");
load_sram_offload((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
load_sram_offload((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
}
/* cli_loop(); */
/* load menu */
fpga_pgm((uint8_t*)"/sd2snes/fpga_base.bit");
fpga_dspx_reset(1);
uart_putc('(');
load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR, 0);
@@ -212,8 +222,8 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
if((rtc_state = rtc_isvalid()) != RTC_OK) {
printf("RTC invalid!\n");
sram_writebyte(0xff, SRAM_STATUS_ADDR+SYS_RTC_STATUS);
set_bcdtime(0x20110401000000LL);
set_fpga_time(0x20110401000000LL);
set_bcdtime(0x20120701000000LL);
set_fpga_time(0x20120701000000LL);
invalidate_rtc();
} else {
printf("RTC valid!\n");
@@ -223,13 +233,14 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
sram_memset(SRAM_SYSINFO_ADDR, 13*40, 0x20);
printf("SNES GO!\n");
snes_reset(1);
delay_ms(1);
fpga_reset_srtc_state();
delay_ms(SNES_RESET_PULSELEN_MS);
sram_writebyte(32, SRAM_CMD_ADDR);
snes_reset(0);
uint8_t cmd = 0;
uint64_t btime = 0;
uint32_t filesize=0;
sram_writebyte(32, SRAM_CMD_ADDR);
printf("test sram\n");
while(!sram_reliable()) cli_entrycheck();
printf("ok\n");
@@ -251,6 +262,7 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
cfg_set_last_game_valid(1);
cfg_save();
filesize = load_rom(file_lfn, SRAM_ROM_ADDR, LOADROM_WITH_SRAM | LOADROM_WITH_RESET);
printf("Filesize = %lu\n", filesize);
break;
case SNES_CMD_SETRTC:
/* get time from RAM */
@@ -265,6 +277,19 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
sysinfo_loop();
cmd=0; /* stay in menu loop */
break;
case SNES_CMD_LOADSPC:
/* load SPC file */
get_selected_name(file_lfn);
printf("Selected name: %s\n", file_lfn);
filesize = load_spc(file_lfn, SRAM_SPC_DATA_ADDR, SRAM_SPC_HEADER_ADDR);
cmd=0; /* stay in menu loop */
break;
case SNES_CMD_RESET:
/* process RESET request from SNES */
printf("RESET requested by SNES\n");
snes_reset_pulse();
cmd=0; /* stay in menu loop */
break;
case SNES_CMD_LOADLAST:
cfg_get_last_game(file_lfn);
printf("Selected name: %s\n", file_lfn);
@@ -276,9 +301,11 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
break;
}
}
printf("loaded %lu bytes\n", filesize);
printf("cmd was %x, going to snes main loop\n", cmd);
if(romprops.has_msu1 && msu1_loop()) {
if(romprops.has_msu1) {
while(!msu1_loop());
prepare_reset();
continue;
}
@@ -286,30 +313,38 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
cmd=0;
uint8_t snes_reset_prev=0, snes_reset_now=0, snes_reset_state=0;
uint16_t reset_count=0;
while(fpga_test() == FPGA_TEST_TOKEN) {
while(fpga_test() == FPGA_TEST_TOKEN)
{
cli_entrycheck();
sleep_ms(250);
sram_reliable();
printf("%s ", get_cic_statename(get_cic_state()));
if(reset_changed) {
if(reset_changed)
{
printf("reset\n");
reset_changed = 0;
fpga_reset_srtc_state();
}
snes_reset_now=get_snes_reset();
if(snes_reset_now) {
if(!snes_reset_prev) {
printf("RESET BUTTON DOWN\n");
snes_reset_state=1;
reset_count=0;
}
} else {
if(snes_reset_prev) {
printf("RESET BUTTON UP\n");
snes_reset_state=0;
}
snes_reset_now = get_snes_reset();
if (snes_reset_now)
{
if (!snes_reset_prev)
{
printf("RESET BUTTON DOWN\n");
snes_reset_state = 1;
reset_count = 0;
}
}
else
{
if (snes_reset_prev)
{
printf("RESET BUTTON UP\n");
snes_reset_state = 0;
}
}
if(snes_reset_state) {
if (snes_reset_state)
{
reset_count++;
} else {
sram_reliable();
@@ -324,7 +359,7 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
}
/* fpga test fail: panic */
if(fpga_test() != FPGA_TEST_TOKEN){
led_panic();
led_panic(LED_PANIC_FPGA_DEAD);
}
/* else reset */
}

View File

@@ -54,11 +54,12 @@ void sram_hexdump(uint32_t addr, uint32_t len) {
uint32_t ptr;
for(ptr=0; ptr < len; ptr += 16) {
sram_readblock((void*)buf, ptr+addr, 16);
uart_trace(buf, 0, 16);
uart_trace(buf, 0, 16, addr);
}
}
void sram_writebyte(uint8_t val, uint32_t addr) {
printf("WriteB %8Xh @%08lXh\n", val, addr);
set_mcu_addr(addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x98); /* WRITE */
@@ -74,10 +75,12 @@ uint8_t sram_readbyte(uint32_t addr) {
FPGA_WAIT_RDY();
uint8_t val = FPGA_RX_BYTE();
FPGA_DESELECT();
//printf(" ReadB %8Xh @%08lXh\n", val, addr);
return val;
}
void sram_writeshort(uint16_t val, uint32_t addr) {
printf("WriteS %8Xh @%08lXh\n", val, addr);
set_mcu_addr(addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x98); /* WRITE */
@@ -89,6 +92,7 @@ void sram_writeshort(uint16_t val, uint32_t addr) {
}
void sram_writelong(uint32_t val, uint32_t addr) {
printf("WriteL %8lXh @%08lXh\n", val, addr);
set_mcu_addr(addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x98); /* WRITE */
@@ -112,6 +116,7 @@ uint16_t sram_readshort(uint32_t addr) {
FPGA_WAIT_RDY();
val |= ((uint32_t)FPGA_RX_BYTE()<<8);
FPGA_DESELECT();
//printf(" ReadS %8lXh @%08lXh\n", val, addr);
return val;
}
@@ -128,6 +133,7 @@ uint32_t sram_readlong(uint32_t addr) {
FPGA_WAIT_RDY();
val |= ((uint32_t)FPGA_RX_BYTE()<<24);
FPGA_DESELECT();
//printf(" ReadL %8lXh @%08lXh\n", val, addr);
return val;
}
@@ -163,7 +169,21 @@ void sram_readblock(void* buf, uint32_t addr, uint16_t size) {
FPGA_DESELECT();
}
void sram_readstrn(void* buf, uint32_t addr, uint16_t size) {
uint16_t count=size;
uint8_t* tgt = buf;
set_mcu_addr(addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x88); /* READ */
while(count--) {
FPGA_WAIT_RDY();
if(!(*(tgt++) = FPGA_RX_BYTE())) break;
}
FPGA_DESELECT();
}
void sram_writeblock(void* buf, uint32_t addr, uint16_t size) {
printf("WriteZ %08lX -> %08lX [%d]\n", addr, addr+size, size);
uint16_t count=size;
uint8_t* src = buf;
set_mcu_addr(addr);
@@ -178,7 +198,7 @@ void sram_writeblock(void* buf, uint32_t addr, uint16_t size) {
uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) {
UINT bytes_read;
DWORD filesize;
DWORD filesize, read_size = 0;
UINT count=0;
tick_t ticksstart, ticks_total=0;
ticksstart=getticks();
@@ -197,19 +217,23 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) {
printf("reconfigure FPGA with %s...\n", romprops.fpga_conf);
fpga_pgm((uint8_t*)romprops.fpga_conf);
}
set_mcu_addr(base_addr);
set_mcu_addr(base_addr + romprops.load_address);
file_open(filename, FA_READ);
ff_sd_offload=1;
sd_offload_tgt=0;
f_lseek(&file_handle, romprops.offset);
for(;;) {
ff_sd_offload=1;
sd_offload_tgt=0;
bytes_read = file_read();
read_size += bytes_read;
if (file_res || !bytes_read) break;
if(!(count++ % 512)) {
uart_putc('.');
}
}
file_close();
printf("Read %ld [%08lX] bytes...\n", read_size, read_size);
set_mapper(romprops.mapper_id);
printf("rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id);
ticks_total=getticks()-ticksstart;
@@ -218,6 +242,8 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) {
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("attempting to load BS data file /sd2snes/bsxpage.bin...\n");
load_sram_offload((uint8_t*)"/sd2snes/bsxpage.bin", 0x900000);
printf("Type: %02x\n", romprops.header.destcode);
set_bsx_regs(0xc0, 0x3f);
uint16_t rombase;
@@ -257,6 +283,9 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) {
rammask = romprops.ramsize_bytes - 1;
}
rommask = romprops.romsize_bytes - 1;
if (rommask >= SRAM_SAVE_ADDR)
rommask = SRAM_SAVE_ADDR - 1;
printf("ramsize=%x rammask=%lx\nromsize=%x rommask=%lx\n", romprops.header.ramsize, rammask, romprops.header.romsize, rommask);
set_saveram_mask(rammask);
set_rom_mask(rommask);
@@ -288,15 +317,90 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) {
if(flags & LOADROM_WITH_RESET) {
fpga_dspx_reset(1);
snes_reset(1);
delay_ms(10);
snes_reset(0);
snes_reset_pulse();
fpga_dspx_reset(0);
}
return (uint32_t)filesize;
}
uint32_t load_spc(uint8_t* filename, uint32_t spc_data_addr, uint32_t spc_header_addr) {
DWORD filesize;
UINT bytes_read;
uint8_t data;
UINT j;
printf("%s\n", filename);
file_open(filename, FA_READ); /* Open SPC file */
if(file_res) return 0;
filesize = file_handle.fsize;
if (filesize < 65920) { /* At this point, we care about filesize only */
file_close(); /* since SNES decides if it is an SPC file */
sram_writebyte(0, spc_header_addr); /* If file is too small, destroy previous SPC header */
return 0;
}
set_mcu_addr(spc_data_addr);
f_lseek(&file_handle, 0x100L); /* Load 64K data segment */
for(;;) {
bytes_read = file_read();
if (file_res || !bytes_read) break;
FPGA_SELECT();
FPGA_TX_BYTE(0x98);
for(j=0; j<bytes_read; j++) {
FPGA_TX_BYTE(file_buf[j]);
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
}
file_close();
file_open(filename, FA_READ); /* Reopen SPC file to reset file_getc state*/
set_mcu_addr(spc_header_addr);
f_lseek(&file_handle, 0x0L); /* Load 256 bytes header */
FPGA_SELECT();
FPGA_TX_BYTE(0x98);
for (j = 0; j < 256; j++) {
data = file_getc();
FPGA_TX_BYTE(data);
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
file_close();
file_open(filename, FA_READ); /* Reopen SPC file to reset file_getc state*/
set_mcu_addr(spc_header_addr+0x100);
f_lseek(&file_handle, 0x10100L); /* Load 128 DSP registers */
FPGA_SELECT();
FPGA_TX_BYTE(0x98);
for (j = 0; j < 128; j++) {
data = file_getc();
FPGA_TX_BYTE(data);
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
file_close(); /* Done ! */
/* clear echo buffer to avoid artifacts */
uint8_t esa = sram_readbyte(spc_header_addr+0x100+0x6d);
uint8_t edl = sram_readbyte(spc_header_addr+0x100+0x7d);
uint8_t flg = sram_readbyte(spc_header_addr+0x100+0x6c);
if(!(flg & 0x20) && (edl & 0x0f)) {
int echo_start = esa << 8;
int echo_length = (edl & 0x0f) << 11;
printf("clearing echo buffer %04x-%04x...\n", echo_start, echo_start+echo_length-1);
sram_memset(spc_data_addr+echo_start, echo_length, 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;
@@ -381,7 +485,6 @@ uint32_t load_bootrle(uint32_t base_addr) {
void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr) {
uint32_t count = 0;
uint32_t num = 0;
FPGA_DESELECT();
file_open(filename, FA_CREATE_ALWAYS | FA_WRITE);
@@ -398,7 +501,7 @@ void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr) {
count++;
}
FPGA_DESELECT();
num = file_write();
file_write();
if(file_res) {
uart_putc(0x30+file_res);
}
@@ -445,9 +548,9 @@ uint8_t sram_reliable() {
val=sram_readlong(SRAM_SCRATCHPAD);
if(val==0x12345678) {
score++;
} else {
printf("i=%d val=%08lX\n", i, val);
}
} //else {
//printf("i=%d val=%08lX\n", i, val);
//}
}
if(score<SRAM_RELIABILITY_SCORE) {
result = 0;
@@ -502,7 +605,6 @@ uint64_t sram_gettime(uint32_t base_addr) {
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;
@@ -526,7 +628,6 @@ void load_dspx(const uint8_t *filename, uint8_t 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;

View File

@@ -30,26 +30,33 @@
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "smc.h"
#define SRAM_ROM_ADDR (0x000000L)
#define SRAM_SAVE_ADDR (0xE00000L)
#define MASK_BITS (0x000000)
#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_SYSINFO_ADDR (0xFF1200L)
#define SRAM_LASTGAME_ADDR (0xFF1420L)
#define SRAM_MENU_SAVE_ADDR (0xFF0000L)
#define SRAM_SCRATCHPAD (0xFFFF00L)
#define SRAM_DIRID (0xFFFFF0L)
#define SRAM_ROM_ADDR ((0x000000L) & ~MASK_BITS)
#define SRAM_SAVE_ADDR ((0x600000L) & ~MASK_BITS)
#define SRAM_MENU_ADDR ((0x500000L) & ~MASK_BITS)
#define SRAM_DIR_ADDR ((0x510000L) & ~MASK_BITS)
#define SRAM_DB_ADDR ((0x580000L) & ~MASK_BITS)
#define SRAM_SPC_DATA_ADDR ((0x7D0000L) & ~MASK_BITS)
#define SRAM_SPC_HEADER_ADDR ((0x7E0000L) & ~MASK_BITS)
#define SRAM_MENU_SAVE_ADDR ((0x7F0000L) & ~MASK_BITS)
#define SRAM_CMD_ADDR ((0x7F1000L) & ~MASK_BITS)
#define SRAM_PARAM_ADDR ((0x7F1004L) & ~MASK_BITS)
#define SRAM_STATUS_ADDR ((0x7F1100L) & ~MASK_BITS)
#define SRAM_SYSINFO_ADDR ((0x7F1200L) & ~MASK_BITS)
#define SRAM_LASTGAME_ADDR ((0x7F1420L) & ~MASK_BITS)
#define SRAM_SCRATCHPAD ((0x7FFF00L) & ~MASK_BITS)
#define SRAM_DIRID ((0x7FFFF0L) & ~MASK_BITS)
#define SRAM_RELIABILITY_SCORE (0x100)
#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_spc(uint8_t* filename, uint32_t spc_data_addr, uint32_t spc_header_addr);
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);
@@ -63,6 +70,7 @@ 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_readstrn(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);

View File

@@ -13,25 +13,132 @@
#include "smc.h"
FIL msufile;
FRESULT msu_res;
DWORD msu_cltbl[CLTBL_SIZE] IN_AHBRAM;
DWORD pcm_cltbl[CLTBL_SIZE] IN_AHBRAM;
UINT msu_audio_bytes_read = 1024;
UINT msu_data_bytes_read = 1;
extern snes_romprops_t romprops;
uint32_t msu_loop_point = 0;
uint32_t msu_page1_start = 0x0000;
uint32_t msu_page2_start = 0x2000;
uint32_t msu_page_size = 0x2000;
uint16_t fpga_status_prev;
uint16_t fpga_status_now;
enum msu_reset_state { MSU_RESET_NONE = 0, MSU_RESET_SHORT, MSU_RESET_LONG };
void prepare_audio_track(uint16_t msu_track) {
/* open file, fill buffer */
char suffix[11];
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);
DBG_MSU1 printf("filename: %s\n", file_buf);
if(f_open(&file_handle, (const TCHAR*)file_buf, FA_READ) == FR_OK) {
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, &msu_audio_bytes_read);
DBG_MSU1 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, &msu_audio_bytes_read);
/* clear busy bit */
set_msu_status(0x00, 0x28); /* set no bits, reset audio_busy + audio_error */
} else {
f_close(&file_handle);
set_msu_status(0x08, 0x20); /* reset audio_busy, set audio_error */
}
}
void prepare_data(uint32_t msu_offset) {
DBG_MSU1 printf("Data requested! Offset=%08lx page1=%08lx page2=%08lx\n", msu_offset, msu_page1_start, msu_page2_start);
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))) {
DBG_MSU1 printf("offset %08lx out of range (%08lx-%08lx, %08lx-%08lx), reload\n", msu_offset, msu_page1_start,
msu_page1_start+msu_page_size-1, msu_page2_start, msu_page2_start+msu_page_size-1);
/* "cache miss" */
/* fill buffer */
set_msu_addr(0x0);
sd_offload_tgt=2;
ff_sd_offload=1;
msu_res = f_lseek(&msufile, msu_offset);
DBG_MSU1 printf("seek to %08lx, res = %d\n", msu_offset, msu_res);
sd_offload_tgt=2;
ff_sd_offload=1;
msu_res = f_read(&msufile, file_buf, 16384, &msu_data_bytes_read);
DBG_MSU1 printf("read res = %d\n", msu_res);
DBG_MSU1 printf("read %d bytes\n", msu_data_bytes_read);
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, &msu_data_bytes_read);
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, &msu_data_bytes_read);
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);
}
int msu1_check_reset(void) {
static tick_t rising_ticks;
static uint8_t resbutton=0, resbutton_prev=0;
int result = MSU_RESET_NONE;
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;
result = MSU_RESET_LONG;
}
} else if(!resbutton && resbutton_prev) { /* release */
if(getticks() < rising_ticks + 99) {
result = MSU_RESET_SHORT;
}
} else {
result = MSU_RESET_NONE;
}
resbutton_prev = resbutton;
return 0;
return result;
}
int msu1_check(uint8_t* filename) {
@@ -54,23 +161,28 @@ int msu1_check(uint8_t* filename) {
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;
fpga_status_prev = fpga_status();
fpga_status_now = fpga_status();
int msu_res;
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, &msu_data_bytes_read);
*/
set_dac_addr(dac_addr);
dac_pause();
dac_reset();
set_msu_addr(0x0);
msu_reset(0x0);
@@ -79,190 +191,110 @@ int msu1_loop() {
f_lseek(&msufile, 0L);
ff_sd_offload=1;
sd_offload_tgt=2;
f_read(&msufile, file_buf, 16384, &bytes_read2);
f_read(&msufile, file_buf, 16384, &msu_data_bytes_read);
set_dac_addr(dac_addr);
dac_pause();
dac_reset();
prepare_audio_track(0);
prepare_data(0);
/* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */
while(1){
while((msu_res = msu1_check_reset()) == MSU_RESET_NONE){
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;
msu_addr = 0x0;
msu_page1_start = msu_page2_start + msu_page_size;
} else {
msu_addr = 0x2000;
msu_page2_start = msu_page1_start + msu_page_size;
pageno = 2;
msu_addr = 0x2000;
msu_page2_start = msu_page1_start + msu_page_size;
}
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);
msu_res = f_read(&msufile, file_buf, 8192, &msu_data_bytes_read);
DBG_MSU1 printf("data buffer refilled. page=%d res=%d page1=%08lx page2=%08lx\n", pageno, msu_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;
dac_addr = 0;
} else {
dac_addr = MSU_DAC_BUFSIZE/2;
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);
f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE/2, &msu_audio_bytes_read);
}
if(fpga_status_now & 0x0020) {
char suffix[11];
/* get trackno */
msu_track = get_msu_track();
DBG_MSU1 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);
DBG_MSU1 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);
DBG_MSU1 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 */
prepare_audio_track(msu_track);
}
if(fpga_status_now & 0x0010) {
/* get address */
msu_offset=get_msu_offset();
DBG_MSU1 printf("Data requested! Offset=%08lx page1=%08lx page2=%08lx\n", msu_offset, msu_page1_start, msu_page2_start);
if( ((msu_offset < msu_page1_start)
|| (msu_offset >= msu_page1_start + msu_page_size))
&& ((msu_offset < msu_page2_start)
|| (msu_offset >= msu_page2_start + msu_page_size))) {
DBG_MSU1 printf("offset %08lx out of range (%08lx-%08lx, %08lx-%08lx), reload\n", msu_offset, msu_page1_start,
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);
prepare_data(msu_offset);
}
if(fpga_status_now & 0x0001) {
if(fpga_status_now & 0x0004) {
msu_repeat = 1;
set_msu_status(0x04, 0x01); /* set bit 2, reset bit 0 */
DBG_MSU1 printf("Repeat set!\n");
msu_repeat = 1;
set_msu_status(0x04, 0x01); /* set bit 2, reset bit 0 */
DBG_MSU1 printf("Repeat set!\n");
} else {
msu_repeat = 0;
set_msu_status(0x00, 0x05); /* set no bits, reset bit 0+2 */
DBG_MSU1 printf("Repeat clear!\n");
msu_repeat = 0;
set_msu_status(0x00, 0x05); /* set no bits, reset bit 0+2 */
DBG_MSU1 printf("Repeat clear!\n");
}
if(fpga_status_now & 0x0002) {
DBG_MSU1 printf("PLAY!\n");
set_msu_status(0x02, 0x01); /* set bit 0, reset bit 1 */
dac_play();
DBG_MSU1 printf("PLAY!\n");
set_msu_status(0x02, 0x01); /* set bit 0, reset bit 1 */
dac_play();
} else {
DBG_MSU1 printf("PAUSE!\n");
set_msu_status(0x00, 0x03); /* set no bits, reset bit 1+0 */
dac_pause();
DBG_MSU1 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) {
if(msu_audio_bytes_read < MSU_DAC_BUFSIZE / 2) {
ff_sd_offload=0;
sd_offload=0;
if(msu_repeat) {
DBG_MSU1 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);
DBG_MSU1 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) - msu_audio_bytes_read, &msu_audio_bytes_read);
} else {
set_msu_status(0x00, 0x02); /* clear play bit */
dac_pause();
set_msu_status(0x00, 0x02); /* clear play bit */
dac_pause();
}
bytes_read = MSU_DAC_BUFSIZE;
}
if(msu1_check_reset()) {
f_close(&msufile);
f_close(&file_handle);
return 1;
msu_audio_bytes_read = MSU_DAC_BUFSIZE;
}
}
f_close(&file_handle);
DBG_MSU1 printf("Reset ");
if(msu_res == MSU_RESET_LONG) {
f_close(&msufile);
DBG_MSU1 printf("to menu\n");
return 1;
}
DBG_MSU1 printf("game\n");
return 0;
}
/* END OF MSU1 STUFF */

View File

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

View File

@@ -21,6 +21,6 @@ void power_init() {
| BV(PCRTC)
| BV(PCGPIO)
| BV(PCPWM1)
// | BV(PCUSB)
| BV(PCUSB)
;
}

View File

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

View File

@@ -857,10 +857,38 @@ void write_block(uint32_t address, uint8_t* buf) {
}
}
/* send STOP_TRANSMISSION after multiple block write
* and reset during_blocktrans status */
void flush_write(void) {
cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
wait_busy();
during_blocktrans = TRANS_NONE;
}
//
// Public functions
//
DRESULT sdn_ioctl(BYTE drv, BYTE cmd, void *buffer) {
DRESULT res;
if(drv >= MAX_CARDS) {
res = STA_NOINIT|STA_NODISK;
} else {
switch(cmd) {
case CTRL_SYNC:
flush_write();
res = RES_OK;
break;
default:
res = RES_PARERR;
}
}
return res;
}
DRESULT disk_ioctl(BYTE drv, BYTE cmd, void *buffer) __attribute__ ((weak, alias("sdn_ioctl")));
DRESULT sdn_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) {
uint8_t sec;
if(drv >= MAX_CARDS) {
@@ -876,7 +904,7 @@ DRESULT sdn_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) {
}
DRESULT disk_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) __attribute__ ((weak, alias("sdn_read")));
DRESULT sdn_initialize(BYTE drv) {
DSTATUS sdn_initialize(BYTE drv) {
uint8_t rsp[17]; /* space for response */
int rsplen;
@@ -905,7 +933,7 @@ DRESULT sdn_initialize(BYTE drv) {
if((rsplen=cmd_slow(SEND_IF_COND, 0x000001aa, 0x87, NULL, rsp))) {
DBG_SD printf("CMD8 response:\n");
DBG_SD uart_trace(rsp, 0, rsplen);
DBG_SD uart_trace(rsp, 0, rsplen, 0);
hcs=1;
}
while(1) {

View File

@@ -22,6 +22,7 @@ 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);
DRESULT sdn_ioctl(BYTE drv, BYTE cmd, void *buffer);
void sdn_changed(void);
uint8_t* sdn_getcid(void);

View File

@@ -59,6 +59,7 @@ void smc_id(snes_romprops_t* props) {
uint8_t score, maxscore=1, score_idx=2; /* assume LoROM */
snes_header_t* header = &(props->header);
props->load_address = 0;
props->has_dspx = 0;
props->has_st0010 = 0;
props->has_cx4 = 0;
@@ -94,6 +95,15 @@ void smc_id(snes_romprops_t* props) {
props->romsize_bytes = 0x100000;
props->expramsize_bytes = 0;
props->mapper_id = 3; /* BS-X Memory Map */
props->region = 0; /* BS-X only existed in Japan */
uint8_t alloc = header->name[0x10];
if(alloc) {
while(!(alloc & 0x01)) {
props->load_address += 0x20000;
alloc >>= 1;
}
}
printf("load address: %lx\n", props->load_address);
return;
}
}
@@ -186,12 +196,19 @@ void smc_id(snes_romprops_t* props) {
}
}
if(header->romsize == 0 || header->romsize > 13) {
header->romsize = 13;
props->romsize_bytes = 1024;
header->romsize = 0;
if(file_handle.fsize >= 1024) {
while(props->romsize_bytes < file_handle.fsize-1) {
header->romsize++;
props->romsize_bytes <<= 1;
}
}
}
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); */
//dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes);
if(props->ramsize_bytes > 32768 || props->ramsize_bytes < 2048) {
props->ramsize_bytes = 0;
}

View File

@@ -84,6 +84,7 @@ typedef struct _snes_romprops {
uint8_t has_cx4; /* CX4 presence flag */
uint8_t fpga_features; /* feature/peripheral enable bits*/
uint8_t region; /* game region (derived from destination code) */
uint32_t load_address; /* where to load the ROM image */
snes_header_t header; /* original header from ROM image */
} snes_romprops_t;

View File

@@ -48,7 +48,7 @@ volatile int reset_pressed;
void prepare_reset() {
snes_reset(1);
delay_ms(1);
delay_ms(SNES_RESET_PULSELEN_MS);
if(romprops.ramsize_bytes && fpga_test() == FPGA_TEST_TOKEN) {
writeled(1);
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
@@ -71,12 +71,22 @@ void snes_init() {
snes_reset(1);
}
void snes_reset_pulse() {
snes_reset(1);
delay_ms(SNES_RESET_PULSELEN_MS);
snes_reset(0);
}
/*
* sets the SNES reset state.
*
* state: put SNES in reset state when 1, release when 0
*/
void snes_reset(int state) {
if (state == 0)
printf("Releasing SNES RESET\n");
else
printf("Pull SNES RESET\n");
BITBAND(SNES_RESET_REG->FIODIR, SNES_RESET_BIT) = state;
}
@@ -117,7 +127,7 @@ void snes_main_loop() {
samecount++;
}
if(diffcount>=1 && samecount==5) {
printf("SaveRAM CRC: 0x%04lx; saving\n", saveram_crc);
printf("SaveRAM CRC: 0x%04lx; saving %s\n", saveram_crc, file_lfn);
writeled(1);
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
writeled(0);
@@ -129,7 +139,7 @@ void snes_main_loop() {
writeled(1);
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
didnotsave=0;
writeled(0);
writeled(1);
}
saveram_crc_old = saveram_crc;
}
@@ -164,12 +174,16 @@ void get_selected_name(uint8_t* fn) {
sram_readblock(fn, addr + 7 + SRAM_MENU_ADDR, 256);
}
void snes_bootprint(void* msg) {
void snes_bootprint(void* msg)
{
printf("%s\n", (char*)msg);
sram_writeblock(msg, SRAM_CMD_ADDR, 33);
}
void snes_menu_errmsg(int err, void* msg) {
void snes_menu_errmsg(int err, void* msg)
{
printf("%d: %s\n", err, (char*)msg);
sram_writeblock(msg, SRAM_CMD_ADDR+1, 64);
sram_writebyte(err, SRAM_CMD_ADDR);
}

View File

@@ -31,15 +31,20 @@
#define SNES_CMD_SETRTC (2)
#define SNES_CMD_SYSINFO (3)
#define SNES_CMD_LOADLAST (4)
#define SNES_CMD_LOADSPC (5)
#define SNES_CMD_RESET (6)
#define MENU_ERR_OK (0)
#define MENU_ERR_NODSP (1)
#define MENU_ERR_NOBSX (2)
#define MENU_ERR_OK (0)
#define MENU_ERR_NODSP (1)
#define MENU_ERR_NOBSX (2)
#define SNES_RESET_PULSELEN_MS (1)
uint8_t crc_valid;
void prepare_reset(void);
void snes_init(void);
void snes_reset_pulse(void);
void snes_reset(int state);
uint8_t get_snes_reset(void);
void snes_main_loop(void);

View File

@@ -15,7 +15,7 @@
*/
uint32_t stat_getstring = 0;
static char sort_str1[21], sort_str2[21];
static char sort_str1[SORT_STRLEN+1], sort_str2[SORT_STRLEN+1];
uint32_t ptrcache[QSORT_MAXELEM] IN_AHBRAM;
/* get element from pointer table in external RAM*/
@@ -50,13 +50,18 @@ int sort_cmp_elem(const void* elem1, const void* elem2) {
if (!(el1 & 0x80000000) && (el2 & 0x80000000)) {
return 1;
}
/*
uint16_t cmp_i;
for(cmp_i=0; cmp_i<8 && sort_long1[cmp_i] == sort_long2[cmp_i]; cmp_i++);
if(cmp_i==8) {
return 0;
if (*sort_str1 == '.') return -1;
if (*sort_str2 == '.') return 1;
/* Do not compare trailing slashes of directory names */
if ((el1 & 0x80000000) && (el2 & 0x80000000)) {
char *str1_slash = strrchr(sort_str1, '/');
char *str2_slash = strrchr(sort_str2, '/');
if(str1_slash != NULL) *str1_slash = 0;
if(str2_slash != NULL) *str2_slash = 0;
}
return sort_long1[cmp_i]-sort_long2[cmp_i]; */
return strcasecmp(sort_str1, sort_str2);
}
@@ -66,13 +71,12 @@ void sort_getstring_for_dirent(char *ptr, uint32_t addr) {
if(addr & 0x80000000) {
/* is directory link, name offset 4 */
leaf_offset = sram_readbyte(addr + 4 + SRAM_MENU_ADDR);
sram_readblock(ptr, addr + 5 + leaf_offset + SRAM_MENU_ADDR, 20);
sram_readstrn(ptr, addr + 5 + leaf_offset + SRAM_MENU_ADDR, SORT_STRLEN);
} else {
/* is file link, name offset 6 */
leaf_offset = sram_readbyte(addr + 6 + SRAM_MENU_ADDR);
sram_readblock(ptr, addr + 7 + leaf_offset + SRAM_MENU_ADDR, 20);
sram_readstrn(ptr, addr + 7 + leaf_offset + SRAM_MENU_ADDR, SORT_STRLEN);
}
ptr[20]=0;
}
void sort_heapify(uint32_t addr, unsigned int i, unsigned int heapsize)

View File

@@ -36,21 +36,13 @@ void spi_preinit() {
BITBAND(LPC_SC->SSP_PCLKREG, SSP_PCLKBIT) = 1;
}
void spi_init(spi_speed_t speed) {
void spi_init() {
/* configure data format - 8 bits, SPI, CPOL=0, CPHA=0, 1 clock per bit */
SSP_REGS->CR0 = (8-1);
/* set clock prescaler */
if (speed == SPI_SPEED_FAST) {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST;
} else if (speed == SPI_SPEED_SLOW) {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW;
} else if (speed == SPI_SPEED_FPGA_FAST) {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST;
} else {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW;
}
SSP_REGS->CPSR = SSP_CLK_DIVISOR;
/* Enable SSP */
SSP_REGS->CR1 = BV(1);
@@ -189,25 +181,3 @@ void spi_rx_block(void *ptr, unsigned int length) {
SSP_REGS->DMACR = 0;
}
}
void spi_set_speed(spi_speed_t speed) {
/* Wait until TX fifo is empty */
while (!BITBAND(SSP_REGS->SR, 0)) ;
/* Disable SSP (FIXME: Is this required?) */
SSP_REGS->CR1 = 0;
/* Change clock divisor */
if (speed == SPI_SPEED_FAST) {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST;
} else if (speed == SPI_SPEED_SLOW) {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW;
} else if (speed == SPI_SPEED_FPGA_FAST) {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST;
} else {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW;
}
/* Enable SSP */
SSP_REGS->CR1 = BV(1);
}

View File

@@ -42,7 +42,7 @@ typedef enum { SPI_SPEED_FAST, SPI_SPEED_SLOW, SPI_SPEED_FPGA_FAST, SPI_SPEED_FP
void spi_preinit(void);
/* Initialize SPI interface */
void spi_init(spi_speed_t speed);
void spi_init(void);
/* Transmit a single byte */
void spi_tx_byte(uint8_t data);
@@ -59,9 +59,6 @@ uint8_t spi_rx_byte(void);
/* Receive a data block */
void spi_rx_block(void *data, unsigned int length);
/* Switch speed of SPI interface */
void spi_set_speed(spi_speed_t speed);
/* wait for SPI TX FIFO to become empty */
void spi_tx_sync(void);

127
src/sysinfo.c Normal file
View File

@@ -0,0 +1,127 @@
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include <arm/bits.h>
#include <string.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 "sdnative.h"
#include "sysinfo.h"
static uint32_t sd_tacc_max, sd_tacc_avg;
void sysinfo_loop() {
sd_tacc_max = 0;
sd_tacc_avg = 0;
while(sram_readbyte(SRAM_CMD_ADDR) != 0x00) {
write_sysinfo();
delay_ms(100);
}
}
void write_sysinfo() {
uint32_t sram_addr = SRAM_SYSINFO_ADDR;
char linebuf[40];
int len;
int sd_ok = 0;
uint8_t *sd_cid = sdn_getcid();
uint32_t sd_tacc_max_int = sd_tacc_max / 1000;
uint32_t sd_tacc_max_frac = sd_tacc_max - (sd_tacc_max_int * 1000);
uint32_t sd_tacc_avg_int = sd_tacc_avg / 1000;
uint32_t sd_tacc_avg_frac = sd_tacc_avg - (sd_tacc_avg_int * 1000);
uint16_t numfiles = sram_readshort(SRAM_DB_ADDR+12);
uint16_t numdirs = sram_readshort(SRAM_DB_ADDR+14);
int32_t sysclk = get_snes_sysclk();
len = snprintf(linebuf, sizeof(linebuf), "Firmware version: %s", CONFIG_VERSION);
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
len = snprintf(linebuf, sizeof(linebuf), " ");
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
if(disk_state == DISK_REMOVED) {
sd_tacc_max = 0;
sd_tacc_avg = 0;
len = snprintf(linebuf, sizeof(linebuf), " ");
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
len = snprintf(linebuf, sizeof(linebuf), " *** SD Card removed *** ");
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
len = snprintf(linebuf, sizeof(linebuf), " ");
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
len = snprintf(linebuf, sizeof(linebuf), " ");
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
sd_ok = 0;
} else {
len = snprintf(linebuf, sizeof(linebuf), "SD Maker/OEM: 0x%02x, \"%c%c\"", sd_cid[1], sd_cid[2], sd_cid[3]);
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
len = snprintf(linebuf, sizeof(linebuf), "SD Product Name: \"%c%c%c%c%c\", Rev. %d.%d", sd_cid[4], sd_cid[5], sd_cid[6], sd_cid[7], sd_cid[8], sd_cid[9]>>4, sd_cid[9]&15);
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
len = snprintf(linebuf, sizeof(linebuf), "SD Serial No.: %02x%02x%02x%02x, Mfd. %d/%02d", sd_cid[10], sd_cid[11], sd_cid[12], sd_cid[13], 2000+((sd_cid[14]&15)<<4)+(sd_cid[15]>>4), sd_cid[15]&15);
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
if(sd_tacc_max)
len = snprintf(linebuf, sizeof(linebuf), "SD acc. time: %ld.%03ld / %ld.%03ld ms avg/max", sd_tacc_avg_int, sd_tacc_avg_frac, sd_tacc_max_int, sd_tacc_max_frac);
else
len = snprintf(linebuf, sizeof(linebuf), "SD acc. time: measuring... ");
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
sd_ok = 1;
}
len = snprintf(linebuf, sizeof(linebuf), " ");
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
len = snprintf(linebuf, sizeof(linebuf), "CIC state: %s", get_cic_statefriendlyname(get_cic_state()));
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
if(sysclk == -1)
len = snprintf(linebuf, sizeof(linebuf), "SNES master clock: measuring...");
else
len = snprintf(linebuf, sizeof(linebuf), "SNES master clock: %ldHz ", get_snes_sysclk());
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
len = snprintf(linebuf, sizeof(linebuf), " ");
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
len = snprintf(linebuf, sizeof(linebuf), "Database: %d files, %d dirs", numfiles, numdirs);
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
len = snprintf(linebuf, sizeof(linebuf), " ");
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_addr += 40;
len = snprintf(linebuf, sizeof(linebuf), " ");
sram_writeblock(linebuf, sram_addr, 40);
sram_memset(sram_addr+len, 40-len, 0x20);
sram_hexdump(SRAM_SYSINFO_ADDR, 13*40);
if(sysclk != -1 && sd_ok)sdn_gettacc(&sd_tacc_max, &sd_tacc_avg);
}

7
src/sysinfo.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef _SYSINFO_H
#define _SYSINFO_H
void write_sysinfo(void);
void sysinfo_loop(void);
#endif

View File

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

View File

@@ -138,7 +138,7 @@ static int8_t parse_wordlist(char *wordlist) {
return -1;
}
if (tolower(c) != tolower(*cur)) {
if (tolower((int)c) != tolower((int)*cur)) {
// Check for end-of-word
if (cur != curchar && (*cur == ' ' || *cur == 0)) {
// Partial match found, return that

View File

@@ -38,7 +38,8 @@
//#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_BAUDRATE 921600
#define CONFIG_UART_BAUDRATE 115200
#define CONFIG_UART_DEADLOCKABLE
#define SSP_CLK_DIVISOR_FAST 2

View File

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

366
src/tests/tests.c Normal file
View File

@@ -0,0 +1,366 @@
/* ___DISCLAIMER___ */
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "bits.h"
#include "config.h"
#include "uart.h"
#include "timer.h"
#include "led.h"
#include "cli.h"
#include "fpga.h"
#include "fpga_spi.h"
#include "ff.h"
#include "fileops.h"
#include "crc32.h"
#include "diskio.h"
#include "cic.h"
#include "rtc.h"
#include "memory.h"
#include "snes.h"
#include "cli.h"
#include "tests.h"
#define PROGRESS ("-\\|/")
int test_sd() {
printf("SD test... please insert card\n=============================\n");
while(disk_status(0) & (STA_NOINIT|STA_NODISK)) cli_entrycheck();
file_open((uint8_t*)"/sd2snes/testfile.bin", FA_WRITE | FA_CREATE_ALWAYS);
if(file_res) {
printf("could not open /sd2snes/testfile.bin: Error %d\n", file_res);
printf("FAILED\n\n\n");
return FAILED;
}
uint32_t testval = 0x55AA55AA;
uint32_t crc = 0;
uint32_t count, blkcount;
for(count=0; count < 8192; count++) {
for(blkcount=0; blkcount < 512; blkcount++) {
file_buf[blkcount] = testval&0xff;
crc=crc32_update(crc, testval&0xff);
testval ^= (crc * (count + blkcount + 7)) - 1;
}
file_write();
}
printf("crc1 = %08lx ", crc);
file_close();
file_open((uint8_t*)"/sd2snes/testfile.bin", FA_READ);
uint32_t crc2 = 0;
for(count=0; count < 8192; count++) {
file_read();
for(blkcount=0; blkcount < 512; blkcount++) {
testval = file_buf[blkcount];
crc2 = crc32_update(crc2, testval&0xff);
}
}
file_close();
printf("crc2 = %08lx ", crc2);
if(crc==crc2) {
printf(" PASSED\n\n\n");
return PASSED;
} else {
printf(" FAILED\n\n\n");
return FAILED;
}
}
int test_cic() {
int cic_state = get_cic_state();
printf("CIC Test:\n=========\n");
printf("Current CIC state: %s\n", get_cic_statename(cic_state));
if(cic_state == CIC_FAIL) {
printf("CIC reports error, push reset...\n");
while((cic_state = get_cic_state()) == CIC_FAIL);
}
if(cic_state == CIC_OK) {
printf("CIC reports OK; no pair mode available. Provoking CIC error...\n");
cic_pair(1,1);
delay_ms(200);
cic_init(0);
printf("new CIC state: %s\n", get_cic_statename(get_cic_state()));
if(get_cic_state() == CIC_FAIL) {
printf("***Please reset SNES***\n");
int failcount=2;
while(failcount--) {
while(get_cic_state() == CIC_FAIL);
delay_ms(200);
}
if(get_cic_state() != CIC_FAIL) {
printf("PASSED\n\n\n");
return PASSED;
}
printf("CIC did not recover properly.\nFAILED\n");
return FAILED;
}
printf("FAILED\n\n\n");
return FAILED;
}
if(cic_state == CIC_SCIC) {
printf("CIC reports OK; pair mode available. Switching to pair mode...\n");
cic_init(1);
delay_ms(100);
cic_pair(0,0);
delay_ms(1000);
printf("new CIC state: %s\n", get_cic_statename(cic_state = get_cic_state()));
if(get_cic_state() != CIC_PAIR) {
printf("FAILED to switch to pair mode!!!\n");
return FAILED;
}
}
if(cic_state == CIC_PAIR) {
cic_init(1);
cic_pair(0,0);
printf("cycling modes, observe power LED color\n");
for(cic_state = 0; cic_state < 17; cic_state++) {
cic_videomode(cic_state & 1);
delay_ms(200);
}
}
printf("PASSED\n\n\n");
return PASSED;
}
int test_rtc() {
struct tm time;
printf("RTC Test\n========\n");
printf("setting clock to 2011-01-01 00:00:00\n");
set_bcdtime(0x20110101000000LL);
printf("waiting 5 seconds\n");
delay_ms(5000);
// uint64_t newtime = get_bcdtime();
printf("new time: ");
read_rtc(&time);
printtime(&time);
if((get_bcdtime() & 0xffffffffffffff) >= 0x20110101000004LL) {
printf("PASSED\n\n\n");
return PASSED;
} else printf("FAILED\n\n\n");
return FAILED;
}
int test_fpga() {
printf("FPGA test\n=========\n");
printf("configuring fpga...\n");
fpga_pgm((uint8_t*)"/sd2snes/test.bit");
printf("basic communication test...");
if(fpga_test() != FPGA_TEST_TOKEN) {
printf("FAILED\n\n\n");
return FAILED;
} else printf("PASSED\n\n\n");
return PASSED;
}
/*************************************************************************************/
/*************************************************************************************/
typedef struct memory_test
{
char name[20];
int a_len;
int d_len;
unsigned int (*read)(unsigned int addr);
void (*write)(unsigned int addr, unsigned int data);
void (*open)(void);
void (*close)(void);
} memory_test;
/*************************************************************************************/
void rom_open(void)
{
snes_reset(1);
fpga_select_mem(0);
FPGA_DESELECT();
delay_ms(1);
FPGA_SELECT();
delay_ms(1);
}
void rom_close(void)
{
}
unsigned int rom_read(unsigned int addr)
{
return sram_readbyte(addr);
}
void rom_write(unsigned int addr, unsigned int data)
{
sram_writebyte(data, addr);
}
memory_test rom = {
.name = "RAM0 (128Mbit)",
.a_len = 22,
.d_len = 8,
.read = rom_read,
.write = rom_write,
.open = rom_open,
.close = rom_close,
};
/*************************************************************************************/
void sram_open(void)
{
snes_reset(1);
fpga_select_mem(1);
}
void sram_close(void)
{
}
unsigned int sram_read(unsigned int addr)
{
return sram_readbyte(addr);
}
void sram_write(unsigned int addr, unsigned int data)
{
sram_writebyte(data, addr);
}
memory_test sram =
{
.name = "RAM1(4Mbit)",
.a_len = 19,
.d_len = 8,
.read = sram_read,
.write = sram_write,
.open = sram_open,
.close = sram_close,
};
int do_test(memory_test *test)
{
int i, j, read, want;
int ret = 0;
int a_mask = (1 << test->a_len) - 1;
int d_mask = (1 << test->d_len) - 1;
test->open();
printf("-- Will test %s\n", test->name);
printf("---- Fill with AA55 ");
test->write(0, 0xAA);
for (i = 1; i < a_mask; i++)
{
if((i&0xffff) == 0)printf("\x8%c", PROGRESS[(i>>16)&3]);
want = (i&1)?0x55:0xAA;
test->write(i, want);
want = ((i-1)&1)?0x55:0xAA;
read = test->read(i-1);
if (read != want)
{
printf("Failed [@%8X Want: %02X Get: %02X]", i-1, want, read);
ret |= 1;
break;
}
}
printf("Ok \n---- Fill with 00 ");
for (i = 0; i < a_mask; i++)
{
if((i&0xffff) == 0)printf("\x8%c", PROGRESS[(i>>16)&3]);
test->write(i, 0);
}
printf("Ok \n---- Check data lines...\n"
"----- ");
for (i = 0; i < test->d_len; i++) printf("%X", i);
printf("\n");
/* Check on 4 addresses, taken evenly */
#define TEST_NUM (10)
for (j = 0; j < TEST_NUM; j ++)
{
printf("----- %8X [", j * a_mask/TEST_NUM);
for (i = 0; i < test->d_len; i++)
{
read = test->read(j * a_mask/TEST_NUM);
if ((test->read(j * a_mask/TEST_NUM) & (1<<i)) != 0)
{
printf("1", read);
ret |= 2;
goto next_data;
}
test->write(j * a_mask/TEST_NUM, (1<<i));
read = test->read(j * a_mask/TEST_NUM);
if (read == 0)
{
printf("0");
ret |= 4;
goto next_data;
}
printf("x");
next_data:
test->write(j * a_mask/4, 0);
}
printf("]\n");
}
test->close();
return ret;
}
int test_mem()
{
int ret = PASSED;
printf("RAM test\n========\n");
if (do_test(&rom) != 0)
ret = FAILED;
if (do_test(&sram) != 0);
ret = FAILED;
return PASSED;
}
int test_clk() {
uint32_t sysclk[4];
int32_t diff, max_diff = 0;
int i, error=0;
printf("sysclk test\n===========\n");
printf("measuring SNES clock...\n");
for(i=0; i<4; i++) {
sysclk[i]=get_snes_sysclk();
if(sysclk[i] < 21000000 || sysclk[i] > 22000000) error = 1;
printf("%lu Hz ", sysclk[i]);
if(i) {
diff = sysclk[i] - sysclk[i-1];
if(diff < 0) diff = -diff;
if(diff > max_diff) max_diff = diff;
printf("diff = %ld max = %ld", diff, max_diff);
}
printf("\n");
delay_ms(1010);
}
if(error) {
printf("clock frequency out of range!\n");
}
if(diff > 1000000) {
printf("clock variation too great!\n");
error = 1;
}
printf(" CPUCLK: %lu\n", get_snes_cpuclk());
printf(" READCLK: %lu\n", get_snes_readclk());
printf(" WRITECLK: %lu\n", get_snes_writeclk());
printf(" PARDCLK: %lu\n", get_snes_pardclk());
printf(" PAWRCLK: %lu\n", get_snes_pawrclk());
printf(" REFRCLK: %lu\n", get_snes_refreshclk());
printf("ROMSELCLK: %lu\n", get_snes_romselclk());
if(error) {
printf("FAILED\n\n\n");
return FAILED;
}
printf("PASSED\n\n\n");
return PASSED;
}

View File

@@ -57,9 +57,17 @@ void timer_init(void) {
/* clear RIT mask */
LPC_RIT->RIMASK = 0; /*xffffffff;*/
/* PCLK = CCLK */
/* PCLK_RIT = CCLK */
BITBAND(LPC_SC->PCLKSEL1, 27) = 0;
BITBAND(LPC_SC->PCLKSEL1, 26) = 1;
/* PCLK_TIMER3 = CCLK/4 */
BITBAND(LPC_SC->PCLKSEL1, 15) = 0;
BITBAND(LPC_SC->PCLKSEL1, 14) = 0;
/* enable timer 3 */
BITBAND(LPC_SC->PCLKSEL1, PCLK_TIMER3) = 1;
/* enable SysTick */
SysTick_Config((SysTick->CALIB & SysTick_CALIB_TENMS_Msk));
}

View File

@@ -238,7 +238,7 @@ void uart_puthex(uint8_t num) {
uart_putc('a'+tmp-10);
}
void uart_trace(void *ptr, uint16_t start, uint16_t len) {
void uart_trace(void *ptr, uint16_t start, uint16_t len, uint32_t addr) {
uint16_t i;
uint8_t j;
uint8_t ch;
@@ -247,8 +247,9 @@ void uart_trace(void *ptr, uint16_t start, uint16_t len) {
data+=start;
for(i=0;i<len;i+=16) {
uart_puthex(start>>8);
uart_puthex(start&0xff);
uart_puthex((addr + start)>>16);
uart_puthex(((addr + start)>>8) & 0xff);
uart_puthex((addr + start)&0xff);
uart_putc('|');
uart_putc(' ');
for(j=0;j<16;j++) {

View File

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

View File

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

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

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

View File

@@ -73,7 +73,7 @@ int main(int argc, char **argv) {
return 1;
}
char *remaining = NULL;
uint32_t version = (uint32_t)strtol(argv[3], &remaining, 10);
uint32_t version = (uint32_t)strtol(argv[3], &remaining, 0);
if(*remaining) {
printf("could not parse version number (remaining portion: %s)\n", remaining);
fclose(f);

Binary file not shown.

Binary file not shown.

View File

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

View File

@@ -33,11 +33,17 @@ module address(
output msu_enable,
output srtc_enable,
output use_bsx,
output bsx_tristate,
input [14:0] bsx_regs,
output dspx_enable,
output dspx_dp_enable,
output dspx_a0,
output r213f_enable
output r213f_enable,
output snescmd_rd_enable,
output snescmd_wr_enable,
input [8:0] bs_page_offset,
input [9:0] bs_page,
input bs_page_enable
);
parameter [2:0]
@@ -76,16 +82,16 @@ assign IS_SAVERAM = SAVERAM_MASK[0]
|| MAPPER == 3'b110
|| MAPPER == 3'b111)
? (!SNES_ADDR[22]
& &SNES_ADDR[21:20]
& SNES_ADDR[21]
& &SNES_ADDR[14:13]
& !SNES_ADDR[15]
)
/* LoROM: SRAM @ Bank 0x70-0x7d, 0xf0-0xfd Offset 0000-7fff
TODO: 0000-ffff for small ROMs? */
/* LoROM: SRAM @ Bank 0x70-0x7d, 0xf0-0xfd
* Offset 0000-7fff for ROM >= 32 MBit, otherwise 0000-ffff */
:(MAPPER == 3'b001)
? (&SNES_ADDR[22:20]
& (SNES_ADDR[19:16] < 4'b1110)
& !SNES_ADDR[15]
& (~SNES_ADDR[15] | ~ROM_MASK[21])
)
/* BS-X: SRAM @ Bank 0x10-0x17 Offset 5000-5fff */
:(MAPPER == 3'b011)
@@ -96,17 +102,38 @@ assign IS_SAVERAM = SAVERAM_MASK[0]
/* BS-X has 4 MBits of extra RAM that can be mapped to various places */
wire [2:0] BSX_PSRAM_BANK = {bsx_regs[2], bsx_regs[6], bsx_regs[5]};
wire [23:0] BSX_CHKADDR = bsx_regs[2] ? SNES_ADDR : {SNES_ADDR[23], 1'b0, SNES_ADDR[22:16], SNES_ADDR[14:0]};
wire BSX_PSRAM_LOHI = (bsx_regs[3] & ~SNES_ADDR[23]) | (bsx_regs[4] & SNES_ADDR[23]);
wire BSX_IS_PSRAM = BSX_PSRAM_LOHI
& (( (BSX_CHKADDR[22:20] == BSX_PSRAM_BANK)
&(SNES_ADDR[15] | bsx_regs[2])
&(~(SNES_ADDR[19] & bsx_regs[2])))
| (bsx_regs[2]
? (SNES_ADDR[22:21] == 2'b01 & SNES_ADDR[15:13] == 3'b011)
: (&SNES_ADDR[22:20] & ~SNES_ADDR[15]))
);
wire BSX_IS_CARTROM = ((bsx_regs[7] & (SNES_ADDR[23:22] == 2'b00))
|(bsx_regs[8] & (SNES_ADDR[23:22] == 2'b10)))
& SNES_ADDR[15];
wire BSX_HOLE_LOHI = (bsx_regs[9] & ~SNES_ADDR[23]) | (bsx_regs[10] & SNES_ADDR[23]);
wire BSX_IS_HOLE = BSX_HOLE_LOHI
& (bsx_regs[2] ? (SNES_ADDR[21:20] == {bsx_regs[11], 1'b0})
: (SNES_ADDR[22:21] == {bsx_regs[11], 1'b0}));
assign bsx_tristate = (MAPPER == 3'b011) & ~BSX_IS_CARTROM & ~BSX_IS_PSRAM & BSX_IS_HOLE;
assign IS_WRITABLE = IS_SAVERAM
|((MAPPER == 3'b011)
?((bsx_regs[3] && SNES_ADDR[23:20]==4'b0110)
|(!bsx_regs[5] && SNES_ADDR[23:20]==4'b0100)
|(!bsx_regs[6] && SNES_ADDR[23:20]==4'b0101)
|(SNES_ADDR[23:19] == 5'b01110)
|(SNES_ADDR[23:21] == 3'b001
&& SNES_ADDR[15:13] == 3'b011)
)
? BSX_IS_PSRAM
: 1'b0);
wire [23:0] BSX_ADDR = bsx_regs[2] ? {1'b0, SNES_ADDR[22:0]}
: {2'b00, SNES_ADDR[22:16], SNES_ADDR[14:0]};
/* BSX regs:
Index Function
1 0=map flash to ROM area; 1=map PRAM to ROM area
@@ -120,45 +147,33 @@ assign IS_WRITABLE = IS_SAVERAM
assign SRAM_SNES_ADDR = ((MAPPER == 3'b000)
?(IS_SAVERAM
? 24'hE00000 + ((SNES_ADDR[14:0] - 15'h6000)
? 24'hE00000 + ({SNES_ADDR[20:16], SNES_ADDR[12:0]}
& SAVERAM_MASK)
: ({1'b0, SNES_ADDR[22:0]} & ROM_MASK))
:(MAPPER == 3'b001)
?(IS_SAVERAM
? 24'hE00000 + (SNES_ADDR[14:0] & SAVERAM_MASK)
? 24'hE00000 + ({SNES_ADDR[20:16], SNES_ADDR[14:0]}
& SAVERAM_MASK)
: ({2'b00, SNES_ADDR[22:16], SNES_ADDR[14:0]}
& ROM_MASK))
:(MAPPER == 3'b010)
?(IS_SAVERAM
? 24'hE00000 + ((SNES_ADDR[14:0] - 15'h6000)
? 24'hE00000 + ({SNES_ADDR[20:16], SNES_ADDR[12:0]}
& SAVERAM_MASK)
: ({1'b0, !SNES_ADDR[23], SNES_ADDR[21:0]}
& ROM_MASK))
:(MAPPER == 3'b011)
?(IS_SAVERAM
? 24'hE00000 + {SNES_ADDR[18:16], SNES_ADDR[11:0]}
: IS_WRITABLE
? (24'h400000 + (SNES_ADDR & 24'h07FFFF))
: ((bsx_regs[7] && SNES_ADDR[23:21] == 3'b000)
|(bsx_regs[8] && SNES_ADDR[23:21] == 3'b100))
?(24'h800000
+ ({1'b0, SNES_ADDR[23:16], SNES_ADDR[14:0]}
& 24'h0FFFFF)
)
:((bsx_regs[1]
? 24'h400000
: 24'h000000
)
+ bsx_regs[2]
?({2'b00, SNES_ADDR[21:0]}
& (ROM_MASK /* >> bsx_regs[1] */)
)
:({1'b0, SNES_ADDR[23:16], SNES_ADDR[14:0]}
& (ROM_MASK /* >> bsx_regs[1] */)
)
)
?( IS_SAVERAM
? 24'hE00000 + {SNES_ADDR[18:16], SNES_ADDR[11:0]}
: BSX_IS_CARTROM
? (24'h800000 + ({SNES_ADDR[22:16], SNES_ADDR[14:0]} & 24'h0fffff))
: BSX_IS_PSRAM
? (24'h400000 + (BSX_ADDR & 24'h07FFFF))
: bs_page_enable
? (24'h900000 + {bs_page,bs_page_offset})
: (BSX_ADDR & 24'h0fffff)
)
:(MAPPER == 3'b110)
?(IS_SAVERAM
@@ -178,7 +193,7 @@ assign SRAM_SNES_ADDR = ((MAPPER == 3'b000)
? 24'hFF0000 + ((SNES_ADDR[14:0] - 15'h6000)
& SAVERAM_MASK)
: (({1'b0, SNES_ADDR[22:0]} & ROM_MASK)
+ 24'hE00000)
+ 24'hC00000)
)
: 24'b0);
@@ -187,14 +202,19 @@ assign ROM_ADDR = SRAM_SNES_ADDR;
assign ROM_SEL = 1'b0;
assign msu_enable_w = featurebits[FEAT_MSU1] & (!SNES_ADDR[22] && ((SNES_ADDR[15:0] & 16'hfff8) == 16'h2000));
reg [5:0] msu_enable_r;
initial msu_enable_r = 6'b000000;
always @(posedge CLK) msu_enable_r <= {msu_enable_r[4:0], msu_enable_w};
assign msu_enable = &msu_enable_r[5:2];
//reg [5:0] msu_enable_r;
//initial msu_enable_r = 6'b000000;
//always @(posedge CLK) msu_enable_r <= {msu_enable_r[4:0], msu_enable_w};
assign msu_enable = msu_enable_w /*&msu_enable_r[5:2]*/;
assign use_bsx = (MAPPER == 3'b011);
assign srtc_enable = featurebits[FEAT_SRTC] & (!SNES_ADDR[22] && ((SNES_ADDR[15:0] & 16'hfffe) == 16'h2800));
assign srtc_enable_w = (!SNES_ADDR[22] && ((SNES_ADDR[15:0] & 16'hfffe) == 16'h2800));
//reg [5:0] srtc_enable_r;
//initial srtc_enable_r = 6'b000000;
//always @(posedge CLK) srtc_enable_r <= {srtc_enable_r[4:0], srtc_enable_w};
assign srtc_enable = srtc_enable_w /*&srtc_enable_r[3:0]*/ & featurebits[FEAT_SRTC];
// DSP1 LoROM: DR=30-3f:8000-bfff; SR=30-3f:c000-ffff
// or DR=60-6f:0000-3fff; SR=60-6f:4000-7fff
@@ -228,15 +248,27 @@ assign dspx_a0 = featurebits[FEAT_DSPX]
assign dspx_dp_enable = dspx_dp_enable_w;
reg [5:0] dspx_enable_r;
initial dspx_enable_r = 6'b000000;
always @(posedge CLK) dspx_enable_r <= {dspx_enable_r[4:0], dspx_enable_w};
assign dspx_enable = &dspx_enable_r[5:2];
//reg [5:0] dspx_enable_r;
//initial dspx_enable_r = 6'b000000;
//always @(posedge CLK) dspx_enable_r <= {dspx_enable_r[4:0], dspx_enable_w};
assign dspx_enable = dspx_enable_w /*&dspx_enable_r[5:1]*/;
wire r213f_enable_w = (SNES_PA == 8'h3f);
reg [5:0] r213f_enable_r;
initial r213f_enable_r = 6'b000000;
always @(posedge CLK) r213f_enable_r <= {r213f_enable_r[4:0], r213f_enable_w};
assign r213f_enable = &r213f_enable_r[5:2] & featurebits[FEAT_213F];
//reg [5:0] r213f_enable_r;
//initial r213f_enable_r = 6'b000000;
//always @(posedge CLK) r213f_enable_r <= {r213f_enable_r[4:0], r213f_enable_w};
assign r213f_enable = r213f_enable_w /*&r213f_enable_r[5:2]*/ & featurebits[FEAT_213F];
wire snescmd_rd_enable_w = (SNES_PA[7:4] == 4'b1111);
//reg [5:0] snescmd_rd_enable_r;
//initial snescmd_rd_enable_r = 6'b000000;
//always @(posedge CLK) snescmd_rd_enable_r <= {snescmd_rd_enable_r[4:0], snescmd_rd_enable_w};
assign snescmd_rd_enable = snescmd_rd_enable_w /*&snescmd_rd_enable_r[5:1]*/;
assign snescmd_wr_enable_w = (SNES_ADDR[23:4] == 20'hccccc);
//reg [5:0] snescmd_wr_enable_r;
//initial snescmd_wr_enable_r = 6'b000000;
//always @(posedge CLK) snescmd_wr_enable_r <= {snescmd_wr_enable_r[4:0], snescmd_wr_enable_w};
assign snescmd_wr_enable = snescmd_wr_enable_w /*&snescmd_wr_enable_r[5:1]*/;
endmodule

View File

@@ -32,7 +32,10 @@ module bsx(
input use_bsx,
output data_ovr,
output flash_writable,
input [55:0] rtc_data
input [59:0] rtc_data,
output [9:0] bs_page_out, // support only page 0000-03ff
output bs_page_enable,
output [8:0] bs_page_offset
);
wire [3:0] reg_addr = snes_addr[19:16]; // 00-0f:5000-5fff
@@ -67,15 +70,44 @@ assign flash_writable = (use_bsx)
&& flash_we_r
&& !is_flash_special_address;
assign data_ovr = cart_enable | base_enable | flash_ovr;
assign data_ovr = (cart_enable | base_enable | flash_ovr) & ~bs_page_enable;
reg [9:0] bs_page0;
reg [9:0] bs_page1;
reg [8:0] bs_page0_offset;
reg [8:0] bs_page1_offset;
reg [4:0] bs_stb0_offset;
reg [4:0] bs_stb1_offset;
wire bs_sta0_en = base_addr == 5'h0a;
wire bs_stb0_en = base_addr == 5'h0b;
wire bs_page0_en = base_addr == 5'h0c;
wire bs_sta1_en = base_addr == 5'h10;
wire bs_stb1_en = base_addr == 5'h11;
wire bs_page1_en = base_addr == 5'h12;
assign bs_page_enable = base_enable & ((|bs_page0 & (bs_page0_en | bs_sta0_en | bs_stb0_en))
|(|bs_page1 & (bs_page1_en | bs_sta1_en | bs_stb1_en)));
assign bs_page_out = (bs_page0_en | bs_sta0_en | bs_stb0_en) ? bs_page0 : bs_page1;
assign bs_page_offset = bs_sta0_en ? 9'h032
: bs_stb0_en ? (9'h034 + bs_stb0_offset)
: bs_sta1_en ? 9'h032
: bs_stb1_en ? (9'h034 + bs_stb1_offset)
: (9'h048 + (bs_page0_en ? bs_page0_offset : bs_page1_offset));
reg [3:0] reg_oe_sreg;
always @(posedge clkin) reg_oe_sreg <= {reg_oe_sreg[2:0], reg_oe};
wire reg_oe_falling = (reg_oe_sreg[3:0] == 4'b1000);
wire reg_oe_falling = (reg_oe_sreg[3:1] == 3'b100);
wire reg_oe_rising = (reg_oe_sreg[3:1] == 3'b001);
reg [1:0] reg_we_sreg;
always @(posedge clkin) reg_we_sreg <= {reg_we_sreg[0], reg_we};
wire reg_we_rising = (reg_we_sreg[1:0] == 2'b01);
reg [2:0] reg_we_sreg;
always @(posedge clkin) reg_we_sreg <= {reg_we_sreg[1:0], reg_we};
wire reg_we_rising = (reg_we_sreg[2:1] == 2'b01);
reg [1:0] pgm_we_sreg;
always @(posedge clkin) pgm_we_sreg <= {pgm_we_sreg[0], pgm_we};
@@ -96,40 +128,40 @@ wire [7:0] rtc_sec = rtc_data[3:0] + (rtc_data[7:4] << 3) + (rtc_data[7:4] << 1)
wire [7:0] rtc_min = rtc_data[11:8] + (rtc_data[15:12] << 3) + (rtc_data[15:12] << 1);
wire [7:0] rtc_hour = rtc_data[19:16] + (rtc_data[23:20] << 3) + (rtc_data[23:20] << 1);
wire [7:0] rtc_day = rtc_data[27:24] + (rtc_data[31:28] << 3) + (rtc_data[31:28] << 1);
/* The following signals are currently unused.
They are kept in case more Satellaview date registers are discovered. */
wire [7:0] rtc_month = rtc_data[35:32] + (rtc_data[39:36] << 3) + (rtc_data[39:36] << 1);
wire [7:0] rtc_dow = {4'b0,rtc_data[59:56]};
wire [7:0] rtc_year1 = rtc_data[43:40] + (rtc_data[47:44] << 3) + (rtc_data[47:44] << 1);
wire [7:0] rtc_year100 = rtc_data[51:48] + (rtc_data[55:52] << 3) + (rtc_data[55:52] << 1);
wire [15:0] rtc_year = (rtc_year100 << 6) + (rtc_year100 << 5) + (rtc_year100 << 2) + rtc_year1;
initial begin
regs_tmpr <= 15'b000000100000000;
regs_outr <= 15'b000000100000000;
regs_tmpr <= 15'b000101111101100;
regs_outr <= 15'b000101111101100;
bsx_counter <= 0;
base_regs[8] <= 0;
base_regs[9] <= 0;
base_regs[10] <= 0;
base_regs[11] <= 8'h9f;
base_regs[12] <= 8'h10;
base_regs[13] <= 8'h9f;
base_regs[14] <= 0;
base_regs[15] <= 0;
base_regs[16] <= 0;
base_regs[17] <= 8'h9f;
base_regs[18] <= 8'h01;
base_regs[19] <= 8'h9f;
base_regs[20] <= 0;
base_regs[21] <= 0;
base_regs[22] <= 8'h02;
base_regs[23] <= 8'hff;
base_regs[24] <= 8'h80;
base_regs[25] <= 8'h01;
base_regs[26] <= 0;
base_regs[27] <= 0;
base_regs[28] <= 0;
base_regs[29] <= 0;
base_regs[30] <= 0;
base_regs[31] <= 0;
base_regs[5'h08] <= 0;
base_regs[5'h09] <= 0;
base_regs[5'h0a] <= 8'h01;
base_regs[5'h0b] <= 0;
base_regs[5'h0c] <= 0;
base_regs[5'h0d] <= 0;
base_regs[5'h0e] <= 0;
base_regs[5'h0f] <= 0;
base_regs[5'h10] <= 8'h01;
base_regs[5'h11] <= 0;
base_regs[5'h12] <= 0;
base_regs[5'h13] <= 0;
base_regs[5'h14] <= 0;
base_regs[5'h15] <= 0;
base_regs[5'h16] <= 0;
base_regs[5'h17] <= 0;
base_regs[5'h18] <= 0;
base_regs[5'h19] <= 0;
base_regs[5'h1a] <= 0;
base_regs[5'h1b] <= 0;
base_regs[5'h1c] <= 0;
base_regs[5'h1d] <= 0;
base_regs[5'h1e] <= 0;
base_regs[5'h1f] <= 0;
flash_vendor_data[3'h0] <= 8'h4d;
flash_vendor_data[3'h1] <= 8'h00;
flash_vendor_data[3'h2] <= 8'h50;
@@ -140,39 +172,55 @@ initial begin
flash_vendor_data[3'h7] <= 8'h00;
flash_ovr_r <= 1'b0;
flash_we_r <= 1'b0;
bs_page0 <= 10'h0;
bs_page1 <= 10'h0;
bs_page0_offset <= 9'h0;
bs_page1_offset <= 9'h0;
bs_stb0_offset <= 5'h00;
bs_stb1_offset <= 5'h00;
end
always @(posedge clkin) begin
if(reg_oe_rising && base_enable) begin
case(base_addr)
5'h0b: begin
bs_stb0_offset <= bs_stb0_offset + 1;
base_regs[5'h0d] <= base_regs[5'h0d] | reg_data_in;
end
5'h0c: bs_page0_offset <= bs_page0_offset + 1;
5'h11: begin
bs_stb1_offset <= bs_stb1_offset + 1;
base_regs[5'h13] <= base_regs[5'h13] | reg_data_in;
end
5'h12: bs_page1_offset <= bs_page1_offset + 1;
endcase
end else
if(reg_oe_falling) begin
if(cart_enable)
reg_data_outr <= {regs_outr[reg_addr], 7'b0};
else if(base_enable) begin
case(base_addr)
5'b10010: begin
if(bsx_counter < 18) begin
bsx_counter <= bsx_counter + 1;
case (bsx_counter)
5:
reg_data_outr <= 8'h1;
6:
reg_data_outr <= 8'h1;
10:
reg_data_outr <= rtc_sec;
11:
reg_data_outr <= rtc_min;
12:
reg_data_outr <= rtc_hour;
default:
reg_data_outr <= 8'h0;
endcase
end else begin
reg_data_outr <= 8'h0;
bsx_counter <= 0;
end
5'h0c, 5'h12: begin
case (bs_page1_offset)
4: reg_data_outr <= 8'h3;
5: reg_data_outr <= 8'h1;
6: reg_data_outr <= 8'h1;
10: reg_data_outr <= rtc_sec;
11: reg_data_outr <= rtc_min;
12: reg_data_outr <= rtc_hour;
13: reg_data_outr <= rtc_dow;
14: reg_data_outr <= rtc_day;
15: reg_data_outr <= rtc_month;
16: reg_data_outr <= rtc_year[7:0];
17: reg_data_outr <= rtc_hour;
default: reg_data_outr <= 8'h0;
endcase
end
5'h0d, 5'h13: begin
reg_data_outr <= base_regs[base_addr];
base_regs[base_addr] <= 8'h00;
end
5'b10011:
reg_data_outr <= base_regs[base_addr] & 8'h3f;
default:
reg_data_outr <= base_regs[base_addr];
endcase
@@ -190,24 +238,35 @@ always @(posedge clkin) begin
end
end else if(pgm_we_rising) begin
regs_tmpr[8:1] <= (regs_tmpr[8:1] | reg_set_bits[7:0]) & ~reg_reset_bits[7:0];
regs_outr[8:1] <= (regs_outr[8:1] | reg_set_bits[7:0]) & ~reg_reset_bits[7:0];
regs_outr[8:1] <= (regs_outr[8:1] | reg_set_bits[7:0]) & ~reg_reset_bits[7:0];
end else if(reg_we_rising && cart_enable) begin
if(reg_addr == 4'he && reg_data_in[7])
regs_outr <= regs_tmpr | 15'b100000000000000;
if(reg_addr == 4'he)
regs_outr <= regs_tmpr;
else
regs_tmpr[reg_addr] <= reg_data_in[7];
end else if(reg_we_rising && base_enable) begin
case(base_addr)
5'h0f: begin
base_regs[base_addr-1] <= base_regs[base_addr]-(base_regs[base_addr-1] >> 1);
base_regs[base_addr] <= base_regs[base_addr] >> 1;
5'h09: begin
base_regs[8'h09] <= reg_data_in;
bs_page0 <= {reg_data_in[1:0], base_regs[8'h08]};
bs_page0_offset <= 9'h00;
end
5'h0b: begin
bs_stb0_offset <= 5'h00;
end
5'h0c: begin
bs_page0_offset <= 9'h00;
end
5'h0f: begin
base_regs[8'h0f] <= reg_data_in;
bs_page1 <= {reg_data_in[1:0], base_regs[8'h0e]};
bs_page1_offset <= 9'h00;
end
5'h11: begin
bsx_counter <= 0;
base_regs[base_addr] <= reg_data_in;
bs_stb1_offset <= 5'h00;
end
5'h12: begin
base_regs[8'h10] <= 8'h80;
bs_page1_offset <= 9'h00;
end
default:
base_regs[base_addr] <= reg_data_in;

View File

@@ -39,7 +39,7 @@ always @(posedge clk) sysclk_sreg <= {sysclk_sreg[0], sysclk};
wire sysclk_rising = (sysclk_sreg == 2'b01);
always @(posedge clk) begin
if(sysclk_counter < 96000000) begin
if(sysclk_counter < 88000000) begin
sysclk_counter <= sysclk_counter + 1;
if(sysclk_rising) sysclk_value <= sysclk_value + 1;
end else begin

View File

@@ -30,7 +30,8 @@ module dac(
input reset,
output sdout,
output lrck,
output mclk,
output mclk,
output sclk,
output DAC_STATUS
);
@@ -68,14 +69,15 @@ reg [15:0] smpshift;
assign mclk = cnt[2]; // mclk = clk/8
assign lrck = cnt[8]; // lrck = mclk/128
wire sclk = cnt[3]; // sclk = lrck*32
assign sclk = cnt[3]; // sclk = lrck*32
reg [2:0] lrck_sreg;
reg [2:0] sclk_sreg;
wire lrck_rising = ({lrck_sreg[2:1]} == 2'b01);
wire lrck_falling = ({lrck_sreg[2:1]} == 2'b10);
wire lrck_rising = (lrck_sreg[1:0] == 2'b01);
wire lrck_falling = (lrck_sreg[1:0] == 2'b10);
wire sclk_rising = ({sclk_sreg[2:1]} == 2'b01);
wire sclk_rising = (sclk_sreg[1:0] == 2'b01);
wire sclk_falling = (sclk_sreg[1:0] == 2'b10);
wire vol_latch_rising = (vol_latch_reg[1:0] == 2'b01);
reg sdout_reg;
@@ -143,17 +145,17 @@ always @(posedge clkin) begin
end
always @(posedge clkin) begin
if (lrck_rising) begin // right channel
smpshift <= (({16'h0, dac_data[31:16]^16'h8000} * vol_reg) >> 8) ^ 16'h8000;
samples <= samples + 1;
end else if (lrck_falling) begin // left channel
smpshift <= (({16'h0, dac_data[15:0]^16'h8000} * vol_reg) >> 8) ^ 16'h8000;
end else begin
if (sclk_rising) begin
smpcnt <= smpcnt + 1;
sdout_reg <= smpshift[15];
if (sclk_falling) begin
smpcnt <= smpcnt + 1;
sdout_reg <= smpshift[15];
if (lrck_rising) begin // right channel
smpshift <= (({16'h0, dac_data[31:16]^16'h8000} * vol_reg) >> 8) ^ 16'h8000;
samples <= samples + 1;
end else if (lrck_falling) begin // left channel
smpshift <= (({16'h0, dac_data[15:0]^16'h8000} * vol_reg) >> 8) ^ 16'h8000;
end else begin
smpshift <= {smpshift[14:0], 1'b0};
end
end
end
end

View File

@@ -1,6 +1,5 @@
NET "CLKIN" TNM_NET = "CLKIN";
TIMESPEC TS_CLKIN = PERIOD "CLKIN" 24 MHz HIGH 50 %;
//TIMESPEC TS_CLKIN = PERIOD "CLKIN" 21.5 MHz HIGH 50 %;
TIMESPEC TS_CLKIN = PERIOD "CLKIN" 22.05 MHz HIGH 50 %;
NET "p113_out" IOSTANDARD = LVCMOS33;
NET "p113_out" LOC = P113;
@@ -8,7 +7,7 @@ NET "p113_out" LOC = P113;
NET "SPI_SCK" LOC = P71;
NET "SPI_SCK" CLOCK_DEDICATED_ROUTE = FALSE;
NET "SPI_SCK" TNM_NET = "SPI_SCK";
TIMESPEC TS_SPI_SCK = PERIOD "SPI_SCK" 48MHz HIGH 50 %;
TIMESPEC TS_SPI_SCK = PERIOD "SPI_SCK" 88.2MHz HIGH 50 %;
NET "SPI_SCK" IOSTANDARD = LVCMOS33;
NET "SPI_SCK" DRIVE = 8;
@@ -33,30 +32,30 @@ NET "ROM_CE" LOC = P172;
NET "ROM_CE" IOSTANDARD = LVCMOS33;
NET "ROM_CE" DRIVE = 8;
NET "SNES_ADDR[0]" LOC = P119;
NET "SNES_ADDR[10]" LOC = P146;
NET "SNES_ADDR[11]" LOC = P148;
NET "SNES_ADDR[12]" LOC = P147;
NET "SNES_ADDR[13]" LOC = P144;
NET "SNES_ADDR[14]" LOC = P141;
NET "SNES_ADDR[15]" LOC = P139;
NET "SNES_ADDR[16]" LOC = P137;
NET "SNES_ADDR[17]" LOC = P133;
NET "SNES_ADDR[18]" LOC = P131;
NET "SNES_ADDR[19]" LOC = P128;
NET "SNES_ADDR[1]" LOC = P122;
NET "SNES_ADDR[20]" LOC = P125;
NET "SNES_ADDR[21]" LOC = P123;
NET "SNES_ADDR[22]" LOC = P120;
NET "SNES_ADDR[23]" LOC = P117;
NET "SNES_ADDR[2]" LOC = P124;
NET "SNES_ADDR[3]" LOC = P126;
NET "SNES_ADDR[4]" LOC = P130;
NET "SNES_ADDR[5]" LOC = P132;
NET "SNES_ADDR[6]" LOC = P135;
NET "SNES_ADDR[7]" LOC = P138;
NET "SNES_ADDR[8]" LOC = P140;
NET "SNES_ADDR[9]" LOC = P143;
NET "SNES_ADDR_IN[0]" LOC = P119;
NET "SNES_ADDR_IN[10]" LOC = P146;
NET "SNES_ADDR_IN[11]" LOC = P148;
NET "SNES_ADDR_IN[12]" LOC = P147;
NET "SNES_ADDR_IN[13]" LOC = P144;
NET "SNES_ADDR_IN[14]" LOC = P141;
NET "SNES_ADDR_IN[15]" LOC = P139;
NET "SNES_ADDR_IN[16]" LOC = P137;
NET "SNES_ADDR_IN[17]" LOC = P133;
NET "SNES_ADDR_IN[18]" LOC = P131;
NET "SNES_ADDR_IN[19]" LOC = P128;
NET "SNES_ADDR_IN[1]" LOC = P122;
NET "SNES_ADDR_IN[20]" LOC = P125;
NET "SNES_ADDR_IN[21]" LOC = P123;
NET "SNES_ADDR_IN[22]" LOC = P120;
NET "SNES_ADDR_IN[23]" LOC = P117;
NET "SNES_ADDR_IN[2]" LOC = P124;
NET "SNES_ADDR_IN[3]" LOC = P126;
NET "SNES_ADDR_IN[4]" LOC = P130;
NET "SNES_ADDR_IN[5]" LOC = P132;
NET "SNES_ADDR_IN[6]" LOC = P135;
NET "SNES_ADDR_IN[7]" LOC = P138;
NET "SNES_ADDR_IN[8]" LOC = P140;
NET "SNES_ADDR_IN[9]" LOC = P143;
NET "SNES_DATA[0]" LOC = P107;
NET "SNES_DATA[1]" LOC = P102;
NET "SNES_DATA[2]" LOC = P100;
@@ -379,54 +378,54 @@ NET "ROM_WE" LOC = P190;
NET "ROM_WE" IOSTANDARD = LVCMOS33;
NET "ROM_WE" DRIVE = 8;
NET "SNES_ADDR[0]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[0]" DRIVE = 8;
NET "SNES_ADDR[10]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[10]" DRIVE = 8;
NET "SNES_ADDR[11]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[11]" DRIVE = 8;
NET "SNES_ADDR[12]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[12]" DRIVE = 8;
NET "SNES_ADDR[13]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[13]" DRIVE = 8;
NET "SNES_ADDR[14]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[14]" DRIVE = 8;
NET "SNES_ADDR[15]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[15]" DRIVE = 8;
NET "SNES_ADDR[16]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[16]" DRIVE = 8;
NET "SNES_ADDR[17]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[17]" DRIVE = 8;
NET "SNES_ADDR[18]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[18]" DRIVE = 8;
NET "SNES_ADDR[19]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[19]" DRIVE = 8;
NET "SNES_ADDR[1]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[1]" DRIVE = 8;
NET "SNES_ADDR[20]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[20]" DRIVE = 8;
NET "SNES_ADDR[21]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[21]" DRIVE = 8;
NET "SNES_ADDR[22]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[22]" DRIVE = 8;
NET "SNES_ADDR[23]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[23]" DRIVE = 8;
NET "SNES_ADDR[2]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[2]" DRIVE = 8;
NET "SNES_ADDR[3]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[3]" DRIVE = 8;
NET "SNES_ADDR[4]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[4]" DRIVE = 8;
NET "SNES_ADDR[5]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[5]" DRIVE = 8;
NET "SNES_ADDR[6]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[6]" DRIVE = 8;
NET "SNES_ADDR[7]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[7]" DRIVE = 8;
NET "SNES_ADDR[8]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[8]" DRIVE = 8;
NET "SNES_ADDR[9]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR[9]" DRIVE = 8;
NET "SNES_ADDR_IN[0]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[0]" DRIVE = 8;
NET "SNES_ADDR_IN[10]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[10]" DRIVE = 8;
NET "SNES_ADDR_IN[11]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[11]" DRIVE = 8;
NET "SNES_ADDR_IN[12]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[12]" DRIVE = 8;
NET "SNES_ADDR_IN[13]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[13]" DRIVE = 8;
NET "SNES_ADDR_IN[14]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[14]" DRIVE = 8;
NET "SNES_ADDR_IN[15]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[15]" DRIVE = 8;
NET "SNES_ADDR_IN[16]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[16]" DRIVE = 8;
NET "SNES_ADDR_IN[17]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[17]" DRIVE = 8;
NET "SNES_ADDR_IN[18]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[18]" DRIVE = 8;
NET "SNES_ADDR_IN[19]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[19]" DRIVE = 8;
NET "SNES_ADDR_IN[1]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[1]" DRIVE = 8;
NET "SNES_ADDR_IN[20]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[20]" DRIVE = 8;
NET "SNES_ADDR_IN[21]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[21]" DRIVE = 8;
NET "SNES_ADDR_IN[22]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[22]" DRIVE = 8;
NET "SNES_ADDR_IN[23]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[23]" DRIVE = 8;
NET "SNES_ADDR_IN[2]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[2]" DRIVE = 8;
NET "SNES_ADDR_IN[3]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[3]" DRIVE = 8;
NET "SNES_ADDR_IN[4]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[4]" DRIVE = 8;
NET "SNES_ADDR_IN[5]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[5]" DRIVE = 8;
NET "SNES_ADDR_IN[6]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[6]" DRIVE = 8;
NET "SNES_ADDR_IN[7]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[7]" DRIVE = 8;
NET "SNES_ADDR_IN[8]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[8]" DRIVE = 8;
NET "SNES_ADDR_IN[9]" IOSTANDARD = LVCMOS33;
NET "SNES_ADDR_IN[9]" DRIVE = 8;
NET "SNES_CPU_CLK" LOC = P95;

View File

@@ -23,7 +23,7 @@ module main(
input CLKIN,
/* SNES signals */
input [23:0] SNES_ADDR,
input [23:0] SNES_ADDR_IN,
input SNES_READ,
input SNES_WRITE,
input SNES_CS,
@@ -76,6 +76,17 @@ module main(
/* debug */
output p113_out
);
wire CLK2;
reg [23:0] SNES_ADDR_r [2:0];
always @(posedge CLK2) begin
SNES_ADDR_r[2] <= SNES_ADDR_r[1];
SNES_ADDR_r[1] <= SNES_ADDR_r[0];
SNES_ADDR_r[0] <= SNES_ADDR_IN;
end
wire [23:0] SNES_ADDR = SNES_ADDR_r[2] & SNES_ADDR_r[1];
wire dspx_dp_enable;
wire [7:0] spi_cmd_data;
@@ -133,6 +144,22 @@ wire [7:0] featurebits;
wire [23:0] MAPPED_SNES_ADDR;
wire ROM_ADDR0;
wire [9:0] bs_page;
wire [8:0] bs_page_offset;
wire bs_page_enable;
wire [4:0] DBG_srtc_state;
wire DBG_srtc_we_rising;
wire [3:0] DBG_srtc_ptr;
wire [5:0] DBG_srtc_we_sreg;
wire [13:0] DBG_msu_address;
wire DBG_msu_reg_oe_rising;
wire DBG_msu_reg_oe_falling;
wire DBG_msu_reg_we_rising;
wire [2:0] SD_DMA_DBG_clkcnt;
wire [10:0] SD_DMA_DBG_cyclecnt;
sd_dma snes_sd_dma(
.CLK(CLK2),
.SD_DAT(SD_DAT),
@@ -146,7 +173,9 @@ sd_dma snes_sd_dma(
.SD_DMA_PARTIAL_START(SD_DMA_PARTIAL_START),
.SD_DMA_PARTIAL_END(SD_DMA_PARTIAL_END),
.SD_DMA_START_MID_BLOCK(SD_DMA_START_MID_BLOCK),
.SD_DMA_END_MID_BLOCK(SD_DMA_END_MID_BLOCK)
.SD_DMA_END_MID_BLOCK(SD_DMA_END_MID_BLOCK),
.DBG_cyclecnt(SD_DMA_DBG_cyclecnt),
.DBG_clkcnt(SD_DMA_DBG_clkcnt)
);
wire SD_DMA_TO_ROM = (SD_DMA_STATUS && (SD_DMA_TGT == 2'b00));
@@ -178,7 +207,11 @@ srtc snes_srtc (
.enable(srtc_enable),
.rtc_data_out(srtc_rtc_data_out),
.rtc_we(srtc_rtc_we),
.reset(srtc_reset)
.reset(srtc_reset),
.srtc_state(DBG_srtc_state),
.srtc_reg_we_rising(DBG_srtc_we_rising),
.srtc_rtc_ptr(DBG_srtc_ptr),
.srtc_we_sreg(DBG_srtc_we_sreg)
);
rtc snes_rtc (
@@ -210,7 +243,12 @@ msu snes_msu (
.status_set_bits(msu_status_set_bits),
.status_reset_we(msu_status_reset_we),
.msu_address_ext(msu_ptr_addr),
.msu_address_ext_write(msu_addr_reset)
.msu_address_ext_write(msu_addr_reset),
.DBG_msu_reg_oe_rising(DBG_msu_reg_oe_rising),
.DBG_msu_reg_oe_falling(DBG_msu_reg_oe_falling),
.DBG_msu_reg_we_rising(DBG_msu_reg_we_rising),
.DBG_msu_address(DBG_msu_address),
.DBG_msu_address_ext_write_rising(DBG_msu_address_ext_write_rising)
);
bsx snes_bsx(
@@ -227,7 +265,11 @@ bsx snes_bsx(
.reg_set_bits(bsx_regs_set_bits),
.data_ovr(bsx_data_ovr),
.flash_writable(IS_FLASHWR),
.rtc_data(rtc_data[55:0])
.rtc_data(rtc_data[59:0]),
.bs_page_out(bs_page), // support only page 0000-03ff
.bs_page_enable(bs_page_enable),
.bs_page_offset(bs_page_offset)
);
spi snes_spi(
@@ -330,7 +372,8 @@ mcu_cmd snes_mcu_cmd(
.mcu_rrq(MCU_RRQ),
.mcu_wrq(MCU_WRQ),
.mcu_rq_rdy(MCU_RDY),
.region_out(mcu_region)
.region_out(mcu_region),
.DBG_mcu_nextaddr(DBG_mcu_nextaddr)
);
wire [7:0] DCM_STATUS;
@@ -343,33 +386,37 @@ my_dcm snes_dcm(
.STATUS(DCM_STATUS)
);
my_dcm snes_dcm2(
.CLKIN(SNES_SYSCLK),
.CLKFX(SYSCLK2),
.RST(DCM_RST)
);
assign DCM_RST=0;
reg [5:0] SNES_PARDr;
reg [5:0] SNES_READr;
reg [5:0] SNES_WRITEr;
reg [5:0] SNES_CPU_CLKr;
reg [7:0] SNES_PARDr;
reg [7:0] SNES_PAWRr;
reg [7:0] SNES_READr;
reg [7:0] SNES_WRITEr;
reg [7:0] SNES_CPU_CLKr;
wire SNES_PARD_start = (SNES_PARDr == 6'b111110);
wire SNES_RD_start = (SNES_READr == 6'b111110);
wire SNES_WR_start = (SNES_WRITEr == 6'b111110);
wire SNES_cycle_start = (SNES_CPU_CLKr[5:0] == 6'b000001);
wire SNES_cycle_end = (SNES_CPU_CLKr[5:0] == 6'b111110);
wire SNES_FAKE_CLK = &SNES_CPU_CLKr[2:1];
//wire SNES_FAKE_CLK = ~(SNES_READ & SNES_WRITE);
always @(posedge SYSCLK2) begin
SNES_PARDr <= {SNES_PARDr[4:0], SNES_PARD};
reg SNES_DEADr;
initial SNES_DEADr = 0;
wire SNES_PARD_start = (SNES_PARDr[7:1] == 7'b1111110);
wire SNES_PAWR_start = (SNES_PAWRr[7:1] == 7'b0000001);
wire SNES_RD_start = (SNES_READr[7:1] == 7'b1111110);
wire SNES_WR_start = (SNES_WRITEr[7:1] == 7'b1111110);
wire SNES_WR_end = (SNES_WRITEr[7:1] == 7'b0000001);
wire SNES_cycle_start = ((SNES_CPU_CLKr[7:2] & SNES_CPU_CLKr[6:1]) == 6'b000001);
wire SNES_cycle_end = ((SNES_CPU_CLKr[7:2] & SNES_CPU_CLKr[6:1]) == 6'b111110);
always @(posedge CLK2) begin
SNES_PARDr <= {SNES_PARDr[6:0], SNES_PARD};
end
always @(posedge CLK2) begin
SNES_READr <= {SNES_READr[4:0], SNES_READ};
SNES_WRITEr <= {SNES_WRITEr[4:0], SNES_WRITE};
SNES_CPU_CLKr <= {SNES_CPU_CLKr[4:0], SNES_CPU_CLK};
SNES_PAWRr <= {SNES_PAWRr[6:0], SNES_PAWR};
SNES_READr <= {SNES_READr[6:0], SNES_READ};
SNES_WRITEr <= {SNES_WRITEr[6:0], SNES_WRITE};
SNES_CPU_CLKr <= {SNES_CPU_CLKr[6:0], SNES_CPU_CLK};
end
address snes_addr(
@@ -390,13 +437,19 @@ address snes_addr(
//BS-X
.use_bsx(use_bsx),
.bsx_regs(bsx_regs),
.bs_page_offset(bs_page_offset),
.bs_page(bs_page),
.bs_page_enable(bs_page_enable),
.bsx_tristate(bsx_tristate),
//SRTC
.srtc_enable(srtc_enable),
//uPD77C25
.dspx_enable(dspx_enable),
.dspx_dp_enable(dspx_dp_enable),
.dspx_a0(DSPX_A0),
.r213f_enable(r213f_enable)
.r213f_enable(r213f_enable),
.snescmd_rd_enable(snescmd_rd_enable),
.snescmd_wr_enable(snescmd_wr_enable)
);
parameter MODE_SNES = 1'b0;
@@ -420,23 +473,27 @@ parameter ST_MCU_WR_WAIT = 18'b000100000000000000;
parameter ST_MCU_WR_WAIT2 = 18'b001000000000000000;
parameter ST_MCU_WR_END = 18'b010000000000000000;
parameter ROM_RD_WAIT = 4'h4;
parameter ROM_RD_WAIT = 4'h1;
parameter ROM_RD_WAIT_MCU = 4'h6;
parameter ROM_WR_WAIT1 = 4'h2;
parameter ROM_WR_WAIT2 = 4'h3;
parameter ROM_WR_WAIT_MCU = 4'h6;
parameter ROM_WR_WAIT = 4'h4;
parameter ROM_WR_WAIT1 = 4'h3;
parameter ROM_WR_WAIT2 = 4'h1;
parameter ROM_WR_WAIT_MCU = 4'h5;
parameter SNES_DEAD_TIMEOUT = 17'd88000; // 1ms
reg [17:0] STATE;
initial STATE = ST_IDLE;
reg [7:0] SNES_DINr;
reg [7:0] SNES_DOUTr;
reg [7:0] ROM_DOUTr;
assign DSPX_SNES_DATA_IN = SNES_DATA;
assign SRTC_SNES_DATA_IN = SNES_DATA[3:0];
assign MSU_SNES_DATA_IN = SNES_DATA;
assign BSX_SNES_DATA_IN = SNES_DATA;
reg [7:0] SNES_DINr;
reg [7:0] ROM_DOUTr;
reg [7:0] r213fr;
reg r213f_forceread;
reg [2:0] r213f_delay;
@@ -446,15 +503,17 @@ initial r213f_forceread = 0;
initial r213f_state = 2'b01;
initial r213f_delay = 3'b011;
reg[7:0] snescmd_regs[15:0];
assign SNES_DATA = (r213f_enable & (!SNES_PARD ^ r213f_forceread)) ? r213fr
:(!SNES_READ ^ r213f_forceread)
assign SNES_DATA = (snescmd_rd_enable & ~SNES_PARD) ? snescmd_regs[SNES_ADDR[3:0]]
:(r213f_enable & ~SNES_PARD & ~r213f_forceread) ? r213fr
:(~SNES_READ ^ (r213f_forceread & r213f_enable & ~SNES_PARD))
? (srtc_enable ? SRTC_SNES_DATA_OUT
:dspx_enable ? DSPX_SNES_DATA_OUT
:dspx_dp_enable ? DSPX_SNES_DATA_OUT
:msu_enable ? MSU_SNES_DATA_OUT
:bsx_data_ovr ? BSX_SNES_DATA_OUT
:SNES_DINr /*(ROM_ADDR0 ? ROM_DATA[7:0] : ROM_DATA[15:8])*/) : 8'bZ;
:SNES_DOUTr /*(ROM_ADDR0 ? ROM_DATA[7:0] : ROM_DATA[15:8])*/) : 8'bZ;
reg [3:0] ST_MEM_DELAYr;
reg MCU_RD_PENDr;
@@ -466,25 +525,39 @@ always @(posedge CLK2) begin
else if(STATE & (ST_SNES_RD_END | ST_SNES_WR_END)) NEED_SNES_ADDRr <= 1'b0;
end
wire ASSERT_SNES_ADDR = SNES_CPU_CLK & NEED_SNES_ADDRr;
assign ROM_ADDR = (SD_DMA_TO_ROM) ? MCU_ADDR[23:1] : (ASSERT_SNES_ADDR) ? MAPPED_SNES_ADDR[23:1] : ROM_ADDRr[23:1];
assign ROM_ADDR0 = (SD_DMA_TO_ROM) ? MCU_ADDR[0] : (ASSERT_SNES_ADDR) ? MAPPED_SNES_ADDR[0] : ROM_ADDRr[0];
reg ROM_WEr;
initial ROM_WEr = 1'b1;
reg RQ_MCU_RDYr;
initial RQ_MCU_RDYr = 1'b1;
assign MCU_RDY = RQ_MCU_RDYr;
reg ROM_SAr;
initial ROM_SAr = 1'b1;
//wire ROM_SA = SNES_FAKE_CLK | ((STATE == ST_IDLE) ^ (~RQ_MCU_RDYr & SNES_cycle_end));
wire ROM_SA = ROM_SAr;
//assign ROM_ADDR = (SD_DMA_TO_ROM) ? MCU_ADDR[23:1] : (ROM_SA) ? MAPPED_SNES_ADDR[23:1] : ROM_ADDRr[23:1];
//assign ROM_ADDR0 = (SD_DMA_TO_ROM) ? MCU_ADDR[0] : (ROM_SA) ? MAPPED_SNES_ADDR[0] : ROM_ADDRr[0];
//WARNING DUE TO BAD SOLDER WE LOST HALF OF THE PSRAM!!!
assign ROM_ADDR = (SD_DMA_TO_ROM) ? MCU_ADDR[22:0] : (ROM_SA) ? MAPPED_SNES_ADDR[22:0] : ROM_ADDRr[22:0];
assign ROM_ADDR0 = 1'b0; //(SD_DMA_TO_ROM) ? MCU_ADDR[0] : (ROM_SA) ? MAPPED_SNES_ADDR[0] : ROM_ADDRr[0];
reg ROM_WEr;
initial ROM_WEr = 1'b1;
reg ROM_DOUT_ENr;
initial ROM_DOUT_ENr = 1'b0;
reg[17:0] SNES_DEAD_CNTr;
initial SNES_DEAD_CNTr = 0;
always @(posedge CLK2) begin
if(MCU_RRQ) begin
MCU_RD_PENDr <= 1'b1;
RQ_MCU_RDYr <= 1'b0;
ROM_ADDRr <= MCU_ADDR;
end else if(MCU_WRQ) begin
MCU_WR_PENDr <= 1'b1;
RQ_MCU_RDYr <= 1'b0;
ROM_ADDRr <= MCU_ADDR;
end else if(STATE & (ST_MCU_RD_END | ST_MCU_WR_END)) begin
MCU_RD_PENDr <= 1'b0;
MCU_WR_PENDr <= 1'b0;
@@ -492,121 +565,127 @@ always @(posedge CLK2) begin
end
end
always @(posedge CLK2) begin
if(~SNES_CPU_CLK) SNES_DEAD_CNTr <= SNES_DEAD_CNTr + 1;
else SNES_DEAD_CNTr <= 17'h0;
end
always @(posedge CLK2) begin
if(SNES_DEAD_CNTr > SNES_DEAD_TIMEOUT) SNES_DEADr <= 1'b1;
else if(SNES_CPU_CLK) SNES_DEADr <= 1'b0;
end
reg snes_wr_cycle;
always @(posedge CLK2) begin
if(SNES_cycle_start & ~SNES_WR_start) begin
STATE <= ST_SNES_RD_ADDR;
end else if(SNES_WR_start) begin
STATE <= ST_SNES_WR_ADDR;
end else begin
case(STATE)
ST_IDLE: begin
ROM_ADDRr <= MAPPED_SNES_ADDR;
if(MCU_RD_PENDr) STATE <= ST_MCU_RD_ADDR;
else if(MCU_WR_PENDr) STATE <= ST_MCU_WR_ADDR;
else STATE <= ST_IDLE;
if(SNES_DEADr & SNES_CPU_CLK) STATE <= ST_IDLE; // interrupt+restart an ongoing MCU access when the SNES comes alive
else
case(STATE)
ST_IDLE: begin
ROM_SAr <= 1'b1;
ROM_DOUT_ENr <= 1'b0;
if(SNES_cycle_start & ~SNES_WRITE) begin
STATE <= ST_SNES_WR_ADDR;
if(IS_WRITABLE | (IS_FLASHWR & ~bsx_tristate)) begin
ROM_WEr <= 1'b0;
end
end else if(SNES_cycle_start) begin
STATE <= ST_SNES_RD_ADDR;
// STATE <= ST_SNES_RD_END;
end else if(SNES_DEADr & MCU_RD_PENDr) begin
STATE <= ST_MCU_RD_ADDR;
end else if(SNES_DEADr & MCU_WR_PENDr) begin
STATE <= ST_MCU_WR_ADDR;
end
ST_SNES_RD_ADDR: begin
STATE <= ST_SNES_RD_WAIT;
ST_MEM_DELAYr <= ROM_RD_WAIT;
end
ST_SNES_RD_ADDR: begin
ST_MEM_DELAYr <= ROM_RD_WAIT;
STATE <= ST_SNES_RD_WAIT;
end
ST_SNES_RD_WAIT: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 1;
if(ST_MEM_DELAYr == 0) begin
STATE <= ST_SNES_RD_END;
SNES_DOUTr <= (ROM_ADDR0 ? ROM_DATA[7:0] : ROM_DATA[15:8]);
end
ST_SNES_RD_WAIT: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
if(ST_MEM_DELAYr == 4'h0) STATE <= ST_SNES_RD_END;
else STATE <= ST_SNES_RD_WAIT;
if(ROM_ADDR0) SNES_DINr <= ROM_DATA[7:0];
else SNES_DINr <= ROM_DATA[15:8];
end
ST_SNES_RD_END: begin
STATE <= ST_IDLE;
if(ROM_ADDR0) SNES_DINr <= ROM_DATA[7:0];
else SNES_DINr <= ROM_DATA[15:8];
end
ST_SNES_WR_ADDR: begin
ROM_WEr <= (!IS_FLASHWR & !IS_WRITABLE);
snes_wr_cycle <= 1'b1;
STATE <= ST_SNES_WR_WAIT1;
ST_MEM_DELAYr <= ROM_WR_WAIT1;
end
ST_SNES_WR_WAIT1: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
if(ST_MEM_DELAYr == 4'h0) STATE <= ST_SNES_WR_DATA;
else STATE <= ST_SNES_WR_WAIT1;
end
ST_SNES_WR_DATA: begin
ROM_DOUTr <= SNES_DATA;
else STATE <= ST_SNES_RD_WAIT;
end
ST_SNES_WR_ADDR: begin
ROM_DOUT_ENr <= 1'b1;
ST_MEM_DELAYr <= ROM_WR_WAIT1;
STATE <= ST_SNES_WR_WAIT1;
end
ST_SNES_WR_WAIT1: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 1;
if(ST_MEM_DELAYr == 0) begin
ST_MEM_DELAYr <= ROM_WR_WAIT2;
STATE <= ST_SNES_WR_WAIT2;
STATE <= ST_SNES_WR_WAIT2;
ROM_DOUTr <= SNES_DATA;
end
ST_SNES_WR_WAIT2: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
if(ST_MEM_DELAYr == 4'h0) STATE <= ST_SNES_WR_END;
else STATE <= ST_SNES_WR_WAIT2;
end
ST_SNES_WR_END: begin
STATE <= ST_IDLE;
else STATE <= ST_SNES_WR_WAIT1;
end
ST_SNES_WR_WAIT2: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 1;
if(ST_MEM_DELAYr == 0) begin
STATE <= ST_SNES_WR_END;
ROM_WEr <= 1'b1;
snes_wr_cycle <= 1'b0;
ROM_DOUT_ENr <= 1'b0;
end
ST_MCU_RD_ADDR: begin
ROM_ADDRr <= MCU_ADDR;
STATE <= ST_MCU_RD_WAIT;
ST_MEM_DELAYr <= ROM_RD_WAIT_MCU;
else STATE <= ST_SNES_WR_WAIT2;
end
ST_SNES_RD_END, ST_SNES_WR_END: begin
// ROM_DOUT_ENr <= 1'b0;
if(MCU_RD_PENDr) begin
STATE <= ST_MCU_RD_ADDR;
end else if(MCU_WR_PENDr) begin
STATE <= ST_MCU_WR_ADDR;
end else STATE <= ST_IDLE;
end
ST_MCU_RD_ADDR: begin
ROM_SAr <= 1'b0;
ST_MEM_DELAYr <= ROM_RD_WAIT_MCU;
STATE <= ST_MCU_RD_WAIT;
end
ST_MCU_RD_WAIT: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 1;
if(ST_MEM_DELAYr == 0) begin
STATE <= ST_MCU_RD_END;
end
ST_MCU_RD_WAIT: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
if(ST_MEM_DELAYr == 4'h0) begin
STATE <= ST_MCU_RD_WAIT2;
ST_MEM_DELAYr <= 4'h2;
end
else STATE <= ST_MCU_RD_WAIT;
if(ROM_ADDR0) MCU_DINr <= ROM_DATA[7:0];
else MCU_DINr <= ROM_DATA[15:8];
end
ST_MCU_RD_WAIT2: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
if(ST_MEM_DELAYr == 4'h0) begin
STATE <= ST_MCU_RD_END;
end else STATE <= ST_MCU_RD_WAIT2;
else STATE <= ST_MCU_RD_WAIT;
end
ST_MCU_RD_END: begin
MCU_DINr <= ROM_DATA[7:0] | ROM_DATA[15:8]; /*ROM_ADDRr[0] ? ROM_DATA[7:0] : ROM_DATA[15:8];*/
STATE <= ST_IDLE;
end
ST_MCU_WR_ADDR: begin
ROM_DOUTr <= MCU_DOUT;
ROM_SAr <= 1'b0;
ST_MEM_DELAYr <= ROM_WR_WAIT_MCU;
STATE <= ST_MCU_WR_WAIT;
ROM_WEr <= 1'b0;
end
ST_MCU_WR_WAIT: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 1;
ROM_DOUT_ENr <= 1'b1;
if(ST_MEM_DELAYr == 0) begin
ROM_WEr <= 1'b1;
STATE <= ST_MCU_WR_END;
end
ST_MCU_RD_END: begin
STATE <= ST_IDLE;
end
ST_MCU_WR_ADDR: begin
ROM_ADDRr <= MCU_ADDR;
STATE <= ST_MCU_WR_WAIT;
ST_MEM_DELAYr <= ROM_WR_WAIT_MCU;
ROM_DOUTr <= MCU_DOUT;
ROM_WEr <= 1'b0;
end
ST_MCU_WR_WAIT: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
if(ST_MEM_DELAYr == 4'h0) begin
ROM_WEr <= 1'b1;
STATE <= ST_MCU_WR_WAIT2;
ST_MEM_DELAYr <= 4'h2;
end
else STATE <= ST_MCU_WR_WAIT;
end
ST_MCU_WR_WAIT2: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
if(ST_MEM_DELAYr == 4'h0) begin
STATE <= ST_MCU_WR_END;
end else STATE <= ST_MCU_WR_WAIT2;
end
ST_MCU_WR_END: begin
STATE <= ST_IDLE;
end
endcase
end
else STATE <= ST_MCU_WR_WAIT;
end
ST_MCU_WR_END: begin
ROM_DOUT_ENr <= 1'b0;
STATE <= ST_IDLE;
end
endcase
end
always @(posedge SYSCLK2) begin
if(SNES_PARD_start & r213f_enable) begin
r213f_forceread <= 1'b1;
r213f_delay <= 3'b001;
always @(posedge CLK2) begin
if(SNES_cycle_end) r213f_forceread <= 1'b1;
else if(SNES_PARD_start & r213f_enable) begin
r213f_delay <= 3'b000;
r213f_state <= 2'b10;
end else if(r213f_state == 2'b10) begin
r213f_delay <= r213f_delay - 1;
@@ -618,46 +697,106 @@ always @(posedge SYSCLK2) begin
end
end
always @(posedge CLK2) begin
if(SNES_WR_end & snescmd_wr_enable) begin
snescmd_regs[SNES_ADDR[3:0]] <= SNES_DATA;
end
end
reg ROM_WE_1;
reg MCU_WRITE_1;
always @(posedge CLK2) begin
ROM_WE_1 <= ROM_WE;
MCU_WRITE_1<= MCU_WRITE;
end
/*
assign ROM_DATA[7:0] = ROM_ADDR0
?(SD_DMA_TO_ROM ? (!MCU_WRITE ? MCU_DOUT : 8'bZ)
: (!ROM_WE ? ROM_DOUTr : 8'bZ)
?(SD_DMA_TO_ROM ? (!MCU_WRITE_1 ? MCU_DOUT : 8'bZ)
//: ((~SNES_WRITE & (IS_WRITABLE | IS_FLASHWR)) ? SNES_DATA
: (ROM_DOUT_ENr ? ROM_DOUTr : 8'bZ) //)
)
:8'bZ;
assign ROM_DATA[15:8] = ROM_ADDR0 ? 8'bZ
:(SD_DMA_TO_ROM ? (!MCU_WRITE ? MCU_DOUT : 8'bZ)
: (!ROM_WE ? ROM_DOUTr : 8'bZ)
:(SD_DMA_TO_ROM ? (!MCU_WRITE_1 ? MCU_DOUT : 8'bZ)
//: ((~SNES_WRITE & (IS_WRITABLE | IS_FLASHWR)) ? SNES_DATA
: (ROM_DOUT_ENr ? ROM_DOUTr : 8'bZ) //)
);
*/
assign ROM_DATA[7:0] = SD_DMA_TO_ROM ? (!MCU_WRITE_1 ? MCU_DOUT : 8'bZ)
: (ROM_DOUT_ENr ? ROM_DOUTr : 8'bZ);
assign ROM_DATA[15:8] = SD_DMA_TO_ROM ? (!MCU_WRITE_1 ? MCU_DOUT : 8'bZ)
: (ROM_DOUT_ENr ? ROM_DOUTr : 8'bZ);
assign ROM_WE = SD_DMA_TO_ROM
?MCU_WRITE
:ROM_WEr | (ASSERT_SNES_ADDR & ~snes_wr_cycle);
:/*(SNES_FAKE_CLK & (IS_WRITABLE | IS_FLASHWR)) ? SNES_WRITE :*/ ROM_WEr;
// OE always active. Overridden by WE when needed.
assign ROM_OE = 1'b0;
assign ROM_CE = 1'b0;
assign ROM_BHE = !ROM_WE ? ROM_ADDR0 : 1'b0;
assign ROM_BLE = !ROM_WE ? !ROM_ADDR0 : 1'b0;
assign ROM_BHE = 1'b0; ///*(~SD_DMA_TO_ROM & ~ROM_WE & ~ROM_SA) ?*/ ROM_ADDR0 /*: 1'b0*/;
assign ROM_BLE = 1'b0; ///*(~SD_DMA_TO_ROM & ~ROM_WE & ~ROM_SA) ?*/ !ROM_ADDR0 /*: 1'b0*/;
assign SNES_DATABUS_OE = (dspx_enable | dspx_dp_enable) ? 1'b0 :
msu_enable ? 1'b0 :
bsx_data_ovr ? (SNES_READ & SNES_WRITE) :
srtc_enable ? (SNES_READ & SNES_WRITE) :
bs_page_enable ? (SNES_READ) :
r213f_enable & !SNES_PARD ? 1'b0 :
(snescmd_wr_enable | snescmd_rd_enable) & !SNES_PARD ? 1'b0 :
((IS_ROM & SNES_CS)
|(!IS_ROM & !IS_SAVERAM & !IS_WRITABLE & !IS_FLASHWR)
|(SNES_READ & SNES_WRITE)
|(SNES_READr[0] & SNES_WRITEr[0])
| bsx_tristate
);
assign SNES_DATABUS_DIR = (!SNES_READ | (!SNES_PARD & r213f_enable))
? 1'b1 ^ r213f_forceread
assign SNES_DATABUS_DIR = (!SNES_READr[0] | (!SNES_PARD & (r213f_enable | snescmd_rd_enable)))
? 1'b1 ^ (r213f_forceread & r213f_enable & ~SNES_PARD)
: 1'b0;
assign IRQ_DIR = 1'b0;
assign SNES_IRQ = 1'bZ;
assign SNES_IRQ = 1'b0;
assign p113_out = 1'b0;
assign p113_out = 1'b1;
/*
wire [35:0] CONTROL0;
icon icon (
.CONTROL0(CONTROL0) // INOUT BUS [35:0]
);
ila_srtc ila (
.CONTROL(CONTROL0), // INOUT BUS [35:0]
.CLK(CLK2), // IN
.TRIG0(SNES_ADDR), // IN BUS [23:0]
.TRIG1(SNES_DATA), // IN BUS [7:0]
.TRIG2({SNES_READ, SNES_WRITE, SNES_CPU_CLK, SNES_cycle_start, SNES_cycle_end, SNES_DEADr, MCU_RRQ, MCU_WRQ, MCU_RDY, ROM_WEr, ROM_WE, ROM_DOUT_ENr, ROM_SA, DBG_mcu_nextaddr, SNES_DATABUS_DIR, SNES_DATABUS_OE}), // IN BUS [15:0]
.TRIG3({bsx_data_ovr, SPI_SCK, SPI_MISO, SPI_MOSI, spi_cmd_ready, spi_param_ready, spi_input_data, SD_DAT}), // IN BUS [17:0]
.TRIG4(ROM_ADDRr), // IN BUS [23:0]
.TRIG5(ROM_DATA), // IN BUS [15:0]
.TRIG6(MCU_DINr), // IN BUS [7:0]
.TRIG7(spi_byte_cnt[3:0])
);
*/
/*
ila_srtc ila (
.CONTROL(CONTROL0), // INOUT BUS [35:0]
.CLK(CLK2), // IN
.TRIG0(SD_DMA_DBG_cyclecnt), // IN BUS [23:0]
.TRIG1(SD_DMA_SRAM_DATA), // IN BUS [7:0]
.TRIG2({SPI_SCK, SPI_MOSI, SPI_MISO, spi_cmd_ready, SD_DMA_SRAM_WE, SD_DMA_EN, SD_CLK, SD_DAT, SD_DMA_NEXTADDR, SD_DMA_STATUS, 3'b000}), // IN BUS [15:0]
.TRIG3({spi_cmd_data, spi_param_data}), // IN BUS [17:0]
.TRIG4(ROM_ADDRr), // IN BUS [23:0]
.TRIG5(ROM_DATA), // IN BUS [15:0]
.TRIG6(MCU_DINr), // IN BUS [7:0]
.TRIG7(ST_MEM_DELAYr)
);
*/
endmodule

View File

@@ -97,7 +97,10 @@ module mcu_cmd(
output reg region_out,
// SNES sync/clk
input snes_sysclk
input snes_sysclk,
// debug
output DBG_mcu_nextaddr
);
initial begin
@@ -140,12 +143,13 @@ reg [55:0] rtc_data_out_buf;
reg rtc_pgm_we_buf;
reg srtc_reset_buf;
initial srtc_reset_buf = 0;
reg [31:0] SNES_SYSCLK_FREQ_BUF;
reg [7:0] MCU_DATA_OUT_BUF;
reg [7:0] MCU_DATA_IN_BUF;
reg [1:0] mcu_nextaddr_buf;
reg [2:0] mcu_nextaddr_buf;
wire mcu_nextaddr;
@@ -198,7 +202,7 @@ always @(posedge clk) begin
SD_DMA_PARTIALr <= cmd_data[2];
end
4'h8: SD_DMA_TGTr <= 2'b00;
4'h9: SD_DMA_TGTr <= cmd_data[1:0]; // not implemented
4'h9: SD_DMA_TGTr <= 2'b00; // cmd_data[1:0]; // not implemented
// 4'hE:
// select memory unit
endcase
@@ -410,9 +414,9 @@ end
// value fetch during last SPI bit
always @(posedge clk) begin
if (cmd_data[7:4] == 4'h8 && mcu_nextaddr_buf == 2'b01)
if (cmd_data[7:4] == 4'h8 && mcu_nextaddr)
MCU_DATA_IN_BUF <= mcu_data_in;
else if (spi_bit_cnt == 3'h7) begin
else if (cmd_ready | param_ready /* bit_cnt == 7 */) begin
if (cmd_data[7:0] == 8'hF0)
MCU_DATA_IN_BUF <= 8'hA5;
else if (cmd_data[7:0] == 8'hF1)
@@ -462,7 +466,7 @@ end
// nextaddr pulse generation
always @(posedge clk) begin
mcu_nextaddr_buf <= {mcu_nextaddr_buf[0], mcu_rq_rdy};
mcu_nextaddr_buf <= {mcu_nextaddr_buf[1:0], mcu_rq_rdy};
end
parameter ST_RQ = 2'b01;
@@ -545,4 +549,5 @@ assign mcu_mapper = MAPPER_BUF;
assign rom_mask_out = ROM_MASK;
assign saveram_mask_out = SAVERAM_MASK;
assign DBG_mcu_nextaddr = mcu_nextaddr;
endmodule

View File

@@ -38,7 +38,13 @@ module msu(
input [5:0] status_set_bits,
input status_reset_we,
input [13:0] msu_address_ext,
input msu_address_ext_write
input msu_address_ext_write,
output DBG_msu_reg_oe_rising,
output DBG_msu_reg_oe_falling,
output DBG_msu_reg_we_rising,
output [13:0] DBG_msu_address,
output DBG_msu_address_ext_write_rising
);
reg [2:0] reg_addr_r [3:0];
@@ -56,13 +62,15 @@ wire status_reset_en = (status_reset_we_r == 2'b01);
reg [13:0] msu_address_r;
wire [13:0] msu_address = msu_address_r;
initial msu_address_r = 13'b0;
wire [7:0] msu_data;
reg [7:0] msu_data_r;
reg [1:0] msu_address_ext_write_sreg;
reg [2:0] msu_address_ext_write_sreg;
always @(posedge clkin)
msu_address_ext_write_sreg <= {msu_address_ext_write_sreg[0], msu_address_ext_write};
wire msu_address_ext_write_rising = (msu_address_ext_write_sreg[1:0] == 2'b01);
msu_address_ext_write_sreg <= {msu_address_ext_write_sreg[1:0], msu_address_ext_write};
wire msu_address_ext_write_rising = (msu_address_ext_write_sreg[2:1] == 2'b01);
reg [4:0] reg_enable_sreg;
initial reg_enable_sreg = 5'b11111;
@@ -70,11 +78,12 @@ always @(posedge clkin) reg_enable_sreg <= {reg_enable_sreg[3:0], enable};
reg [5:0] reg_oe_sreg;
always @(posedge clkin) reg_oe_sreg <= {reg_oe_sreg[4:0], reg_oe};
wire reg_oe_rising = reg_enable_sreg[4] && (reg_oe_sreg[5:0] == 6'b000001);
wire reg_oe_rising = reg_enable_sreg[4] && (reg_oe_sreg[5:1] == 5'b00001);
wire reg_oe_falling = reg_enable_sreg[1] && (reg_oe_sreg[5:1] == 5'b11110);
reg [5:0] reg_we_sreg;
always @(posedge clkin) reg_we_sreg <= {reg_we_sreg[4:0], reg_we};
wire reg_we_rising = reg_enable_sreg[4] && (reg_we_sreg[5:0] == 6'b000001);
wire reg_we_rising = reg_enable_sreg[4] && (reg_we_sreg[5:1] == 5'b00001);
reg [31:0] addr_out_r;
assign addr_out = addr_out_r;
@@ -93,14 +102,27 @@ reg audio_busy_r;
reg data_start_r;
reg data_busy_r;
reg ctrl_start_r;
reg audio_error_r;
reg [1:0] audio_ctrl_r;
reg [1:0] audio_status_r;
initial begin
audio_busy_r <= 1'b1;
data_busy_r <= 1'b1;
audio_busy_r = 1'b1;
data_busy_r = 1'b1;
audio_error_r = 1'b0;
volume_r = 8'h00;
addr_out_r = 32'h00000000;
track_out_r = 16'h0000;
data_start_r = 1'b0;
audio_start_r = 1'b0;
end
assign DBG_msu_address = msu_address;
assign DBG_msu_reg_oe_rising = reg_oe_rising;
assign DBG_msu_reg_oe_falling = reg_oe_falling;
assign DBG_msu_reg_we_rising = reg_we_rising;
assign DBG_msu_address_ext_write_rising = msu_address_ext_write_rising;
assign status_out = {msu_address_r[13], // 6
audio_start_r, // 5
data_start_r, // 4
@@ -124,8 +146,8 @@ reg [7:0] data_out_r;
assign reg_data_out = data_out_r;
always @(posedge clkin) begin
case(reg_addr_r[3])
3'h0: data_out_r <= {data_busy_r, audio_busy_r, audio_status_r, 4'b0001};
case(reg_addr_r[1])
3'h0: data_out_r <= {data_busy_r, audio_busy_r, audio_status_r, audio_error_r, 3'b001};
3'h1: data_out_r <= msu_data;
3'h2: data_out_r <= 8'h53;
3'h3: data_out_r <= 8'h2d;
@@ -138,7 +160,7 @@ end
always @(posedge clkin) begin
if(reg_we_rising) begin
case(reg_addr_r[3])
case(reg_addr_r[1])
3'h0: addr_out_r[7:0] <= reg_data_in;
3'h1: addr_out_r[15:8] <= reg_data_in;
3'h2: addr_out_r[23:16] <= reg_data_in;
@@ -173,7 +195,7 @@ always @(posedge clkin) begin
data_busy_r <= (data_busy_r | status_set_bits[4]) & ~status_reset_bits[4];
if(status_reset_bits[4]) data_start_r <= 1'b0;
// volume_start_r <= (volume_start_r | status_set_bits[3]) & ~status_reset_bits[3];
audio_error_r <= (audio_error_r | status_set_bits[3]) & ~status_reset_bits[3];
audio_status_r <= (audio_status_r | status_set_bits[2:1]) & ~status_reset_bits[2:1];

View File

@@ -42,7 +42,7 @@ reg [31:0] tick_cnt;
always @(posedge clkin) begin
tick_cnt <= tick_cnt + 1;
if((tick_cnt == 24000000) || pgm_we_rising) tick_cnt <= 0;
if((tick_cnt == 22000000) || pgm_we_rising) tick_cnt <= 0;
end
assign rtc_data = rtc_data_out_r;

View File

@@ -9,107 +9,91 @@
<!-- along with the project source files, is sufficient to open and -->
<!-- implement in ISE Project Navigator. -->
<!-- -->
<!-- Copyright (c) 1995-2011 Xilinx, Inc. All rights reserved. -->
<!-- Copyright (c) 1995-2012 Xilinx, Inc. All rights reserved. -->
</header>
<version xil_pn:ise_version="13.2" xil_pn:schema_version="2"/>
<version xil_pn:ise_version="14.2" xil_pn:schema_version="2"/>
<files>
<file xil_pn:name="address.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="1"/>
<association xil_pn:name="Implementation" xil_pn:seqID="17"/>
</file>
<file xil_pn:name="bsx.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="2"/>
<association xil_pn:name="Implementation" xil_pn:seqID="16"/>
</file>
<file xil_pn:name="clk_test.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="3"/>
<association xil_pn:name="Implementation" xil_pn:seqID="6"/>
</file>
<file xil_pn:name="dac.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="4"/>
<association xil_pn:name="Implementation" xil_pn:seqID="15"/>
</file>
<file xil_pn:name="dcm.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="5"/>
<association xil_pn:name="Implementation" xil_pn:seqID="14"/>
</file>
<file xil_pn:name="main.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="6"/>
<association xil_pn:name="Implementation" xil_pn:seqID="18"/>
</file>
<file xil_pn:name="mcu_cmd.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="7"/>
<association xil_pn:name="Implementation" xil_pn:seqID="13"/>
</file>
<file xil_pn:name="msu.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="8"/>
<association xil_pn:name="Implementation" xil_pn:seqID="12"/>
</file>
<file xil_pn:name="rtc.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="9"/>
<association xil_pn:name="Implementation" xil_pn:seqID="11"/>
</file>
<file xil_pn:name="sd_dma.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="10"/>
<association xil_pn:name="Implementation" xil_pn:seqID="10"/>
</file>
<file xil_pn:name="spi.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="11"/>
<association xil_pn:name="Implementation" xil_pn:seqID="9"/>
</file>
<file xil_pn:name="srtc.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="12"/>
<association xil_pn:name="Implementation" xil_pn:seqID="8"/>
</file>
<file xil_pn:name="upd77c25.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="4"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="13"/>
<association xil_pn:name="Implementation" xil_pn:seqID="7"/>
</file>
<file xil_pn:name="main.ucf" xil_pn:type="FILE_UCF">
<association xil_pn:name="Implementation" xil_pn:seqID="0"/>
</file>
<file xil_pn:name="main_tf.v" xil_pn:type="FILE_VERILOG"/>
<file xil_pn:name="updtest_tf.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="PostMapSimulation" xil_pn:seqID="19"/>
<association xil_pn:name="PostRouteSimulation" xil_pn:seqID="19"/>
<association xil_pn:name="PostTranslateSimulation" xil_pn:seqID="19"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="14"/>
<association xil_pn:name="PostMapSimulation" xil_pn:seqID="14"/>
<association xil_pn:name="PostRouteSimulation" xil_pn:seqID="14"/>
<association xil_pn:name="PostTranslateSimulation" xil_pn:seqID="14"/>
</file>
<file xil_pn:name="ipcore_dir/upd77c25_datram.xco" xil_pn:type="FILE_COREGEN">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="3"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="15"/>
<association xil_pn:name="Implementation" xil_pn:seqID="3"/>
</file>
<file xil_pn:name="ipcore_dir/upd77c25_datrom.xco" xil_pn:type="FILE_COREGEN">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="2"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="16"/>
<association xil_pn:name="Implementation" xil_pn:seqID="2"/>
</file>
<file xil_pn:name="ipcore_dir/upd77c25_pgmrom.xco" xil_pn:type="FILE_COREGEN">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="1"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="17"/>
<association xil_pn:name="Implementation" xil_pn:seqID="1"/>
</file>
<file xil_pn:name="ipcore_dir/dac_buf.xco" xil_pn:type="FILE_COREGEN">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="18"/>
<association xil_pn:name="Implementation" xil_pn:seqID="5"/>
</file>
<file xil_pn:name="ipcore_dir/msu_databuf.xco" xil_pn:type="FILE_COREGEN">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="19"/>
<association xil_pn:name="Implementation" xil_pn:seqID="4"/>
</file>
<file xil_pn:name="ipcore_dir/upd77c25_datram.xise" xil_pn:type="FILE_COREGENISE">
<association xil_pn:name="Implementation" xil_pn:seqID="0"/>
</file>
<file xil_pn:name="ipcore_dir/upd77c25_datrom.xise" xil_pn:type="FILE_COREGENISE">
<association xil_pn:name="Implementation" xil_pn:seqID="0"/>
</file>
<file xil_pn:name="ipcore_dir/upd77c25_pgmrom.xise" xil_pn:type="FILE_COREGENISE">
<association xil_pn:name="Implementation" xil_pn:seqID="0"/>
</file>
<file xil_pn:name="ipcore_dir/dac_buf.xise" xil_pn:type="FILE_COREGENISE">
<association xil_pn:name="Implementation" xil_pn:seqID="0"/>
</file>
<file xil_pn:name="ipcore_dir/msu_databuf.xise" xil_pn:type="FILE_COREGENISE">
<file xil_pn:name="main.ucf" xil_pn:type="FILE_UCF">
<association xil_pn:name="Implementation" xil_pn:seqID="0"/>
</file>
</files>
@@ -377,8 +361,8 @@
<property xil_pn:name="Specify Top Level Instance Names Post-Route" xil_pn:value="work.updtest" xil_pn:valueState="default"/>
<property xil_pn:name="Specify Top Level Instance Names Post-Translate" xil_pn:value="work.updtest" xil_pn:valueState="default"/>
<property xil_pn:name="Speed Grade" xil_pn:value="-4" xil_pn:valueState="non-default"/>
<property xil_pn:name="Starting Placer Cost Table (1-100) Map" xil_pn:value="6" xil_pn:valueState="non-default"/>
<property xil_pn:name="Starting Placer Cost Table (1-100) Par" xil_pn:value="6" xil_pn:valueState="non-default"/>
<property xil_pn:name="Starting Placer Cost Table (1-100) Map" xil_pn:value="11" xil_pn:valueState="non-default"/>
<property xil_pn:name="Starting Placer Cost Table (1-100) Par" xil_pn:value="11" xil_pn:valueState="non-default"/>
<property xil_pn:name="Structure window" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Synthesis Tool" xil_pn:value="XST (VHDL/Verilog)" xil_pn:valueState="default"/>
<property xil_pn:name="Target Simulator" xil_pn:value="Please Specify" xil_pn:valueState="default"/>
@@ -449,9 +433,7 @@
<property xil_pn:name="PROP_intWorkingDirUsed" xil_pn:value="No" xil_pn:valueState="non-default"/>
</properties>
<bindings>
<binding xil_pn:location="/main" xil_pn:name="main.ucf"/>
</bindings>
<bindings/>
<libraries/>

View File

@@ -31,7 +31,10 @@ module sd_dma(
input [10:0] SD_DMA_PARTIAL_START,
input [10:0] SD_DMA_PARTIAL_END,
input SD_DMA_START_MID_BLOCK,
input SD_DMA_END_MID_BLOCK
input SD_DMA_END_MID_BLOCK,
output [10:0] DBG_cyclecnt,
output [2:0] DBG_clkcnt
);
reg [10:0] SD_DMA_STARTr;
@@ -74,7 +77,11 @@ assign SD_DMA_SRAM_DATA = SD_DMA_SRAM_DATAr;
reg [2:0] clkcnt;
initial clkcnt = 3'b000;
reg [1:0] SD_CLKr;
always @(posedge CLK) SD_CLKr <= {SD_CLKr[0], clkcnt[1]};
initial SD_CLKr = 3'b111;
always @(posedge CLK)
if(SD_DMA_EN_rising) SD_CLKr <= 3'b111;
else SD_CLKr <= {SD_CLKr[0], clkcnt[1]};
assign SD_CLK = SD_DMA_STATUSr ? SD_CLKr[1] : 1'bZ;
always @(posedge CLK) begin
@@ -116,20 +123,20 @@ always @(posedge CLK) begin
if(SD_DMA_STATUSr) begin
case(clkcnt[2:0])
3'h0: begin
SD_DMA_SRAM_WEr <= 1'b1;
SD_DMA_SRAM_DATAr[7:4] <= SD_DAT;
if(cyclecnt>SD_DMA_STARTr && cyclecnt <= SD_DMA_ENDr) SD_DMA_NEXTADDRr <= 1'b1;
end
3'h1:
3'h1: begin
SD_DMA_NEXTADDRr <= 1'b0;
// 3'h2:
3'h3:
if(cyclecnt>=SD_DMA_STARTr && cyclecnt < SD_DMA_ENDr) SD_DMA_SRAM_WEr <= 1'b0;
end
3'h2: if(cyclecnt>=SD_DMA_STARTr && cyclecnt < SD_DMA_ENDr) SD_DMA_SRAM_WEr <= 1'b0;
// 3'h3:
3'h4:
SD_DMA_SRAM_DATAr[3:0] <= SD_DAT;
// 3'h5:
// 3'h6:
// 3'h7:
3'h7:
SD_DMA_SRAM_WEr <= 1'b1;
endcase
end
end

View File

@@ -39,15 +39,27 @@ module spi(
reg [7:0] cmd_data_r;
reg [7:0] param_data_r;
reg [1:0] SSELr; always @(posedge clk) SSELr <= {SSELr[0], SSEL};
reg [2:0] SSELr;
reg [2:0] SSELSCKr;
always @(posedge clk) SSELr <= {SSELr[1:0], SSEL};
always @(posedge SCK) SSELSCKr <= {SSELSCKr[1:0], SSEL};
wire SSEL_inactive = SSELr[1];
wire SSEL_active = ~SSELr[1]; // SSEL is active low
wire SSEL_startmessage = (SSELr[1:0]==2'b10); // message starts at falling edge
wire SSEL_endmessage = (SSELr[1:0]==2'b01); // message stops at rising edge
wire SSEL_startmessage = (SSELr[2:1]==2'b10); // message starts at falling edge
wire SSEL_endmessage = (SSELr[2:1]==2'b01); // message stops at rising edge
assign endmessage = SSEL_endmessage;
assign startmessage = SSEL_startmessage;
// bit count for one SPI byte + byte count for the message
reg [2:0] bitcnt;
initial bitcnt = 3'b000;
wire bitcnt_msb = bitcnt[2];
reg [2:0] bitcnt_wrap_r;
always @(posedge clk) bitcnt_wrap_r <= {bitcnt_wrap_r[1:0], bitcnt_msb};
wire byte_received_sync = (bitcnt_wrap_r[2:1] == 2'b10);
reg [31:0] byte_cnt_r;
reg byte_received; // high when a byte has been received
@@ -56,23 +68,26 @@ reg [7:0] byte_data_received;
assign bit_cnt = bitcnt;
always @(posedge SCK) begin
if(SSEL) bitcnt <= 3'b000;
else begin
bitcnt <= bitcnt + 3'b001;
if(SSELSCKr[1]) bitcnt <= 3'b000;
else bitcnt <= bitcnt + 3'b001;
end
always @(posedge SCK) begin
if(~SSELSCKr[1]) begin
byte_data_received <= {byte_data_received[6:0], MOSI};
end
if(~SSEL && bitcnt==3'b111) byte_received <= 1'b1;
if(~SSELSCKr[1] && bitcnt==3'b111) byte_received <= 1'b1;
else byte_received <= 1'b0;
end
reg [1:0] byte_received_r;
always @(posedge clk) byte_received_r <= {byte_received_r[0], byte_received};
wire byte_received_sync = (byte_received_r == 2'b01);
//reg [2:0] byte_received_r;
//always @(posedge clk) byte_received_r <= {byte_received_r[1:0], byte_received};
//wire byte_received_sync = (byte_received_r[2:1] == 2'b01);
always @(posedge clk) begin
if(~SSEL_active)
if(SSEL_inactive) begin
byte_cnt_r <= 16'h0000;
else if(byte_received_sync) begin
end else if(byte_received_sync) begin
byte_cnt_r <= byte_cnt_r + 16'h0001;
end
end

View File

@@ -29,7 +29,13 @@ module srtc(
input reg_oe,
input enable,
output rtc_we,
input reset
input reset,
/* DEBUG */
output [4:0] srtc_state,
output srtc_reg_we_rising,
output [3:0] srtc_rtc_ptr,
output [5:0] srtc_we_sreg
);
reg [59:0] rtc_data_r;
@@ -44,13 +50,14 @@ reg rtc_we_r;
assign rtc_we = rtc_we_r;
assign data_out = data_out_r;
reg [3:0] reg_oe_sreg;
always @(posedge clkin) reg_oe_sreg <= {reg_oe_sreg[2:0], reg_oe};
wire reg_oe_falling = (reg_oe_sreg == 4'b1000);
reg [5:0] reg_oe_sreg;
always @(posedge clkin) reg_oe_sreg <= {reg_oe_sreg[4:0], reg_oe};
wire reg_oe_falling = (reg_oe_sreg[5:1] == 5'b11110);
wire reg_oe_rising = (reg_oe_sreg[5:1] == 5'b00001);
reg [1:0] reg_we_sreg;
always @(posedge clkin) reg_we_sreg <= {reg_we_sreg[0], reg_we};
wire reg_we_rising = (reg_we_sreg[1:0] == 2'b01);
reg [5:0] reg_we_sreg;
always @(posedge clkin) reg_we_sreg <= {reg_we_sreg[4:0], reg_we};
wire reg_we_rising = (reg_we_sreg[5:1] == 5'b00001);
reg [1:0] reset_sreg;
always @(posedge clkin) reset_sreg <= {reset_sreg[0], reset};
@@ -64,27 +71,37 @@ parameter SRTC_COMMAND = 5'b00100;
parameter SRTC_WRITE = 5'b01000;
parameter SRTC_WRITE2 = 5'b10000;
reg [3:0] data_in_r;
reg [3:0] addr_in_r;
always @(posedge clkin) addr_in_r <= {addr_in_r[2:0], addr_in};
assign srtc_reg_we_rising = reg_we_rising;
assign srtc_state = mode_r;
assign srtc_rtc_ptr = rtc_ptr;
assign srtc_we_sreg = reg_we_sreg;
initial begin
rtc_we_r = 0;
mode_r <= SRTC_READ;
rtc_ptr <= 4'hf;
mode_r = SRTC_READ;
rtc_ptr = 4'hf;
data_out_r = 8'h00;
end
//always @(posedge clkin) data_in_r <= data_in;
always @(posedge clkin) begin
if(~reg_we) data_in_r <= data_in;
end
always @(posedge clkin) begin
if(reset_rising) begin
mode_r <= SRTC_READ;
rtc_ptr <= 4'hf;
end else if(mode_r == SRTC_WRITE2) begin
we_countdown_r <= we_countdown_r - 1;
if (we_countdown_r == 3'b000) begin
mode_r <= SRTC_WRITE;
rtc_we_r <= 0;
end
end else if(reg_we_rising && enable) begin
case (addr_in)
case (addr_in_r[0])
// 1'b0: // data register is read only
1'b1: // control register
case (data_in)
case (data_in_r)
4'hd: begin
mode_r <= SRTC_READ;
rtc_ptr <= 4'hf;
@@ -92,11 +109,9 @@ always @(posedge clkin) begin
4'he: begin
mode_r <= SRTC_COMMAND;
end
4'hf: begin
end
default: begin
if(mode_r == SRTC_COMMAND) begin
case (data_in)
case (data_in_r)
4'h0: begin
mode_r <= SRTC_WRITE;
rtc_data_out_r <= rtc_data_in;
@@ -112,38 +127,38 @@ always @(posedge clkin) begin
end else if(mode_r == SRTC_WRITE) begin
rtc_ptr <= rtc_ptr + 1;
case(rtc_ptr)
0: rtc_data_out_r[3:0] <= data_in;
1: rtc_data_out_r[7:4] <= data_in;
2: rtc_data_out_r[11:8] <= data_in;
3: rtc_data_out_r[15:12] <= data_in;
4: rtc_data_out_r[19:16] <= data_in;
5: rtc_data_out_r[23:20] <= data_in;
6: rtc_data_out_r[27:24] <= data_in;
7: rtc_data_out_r[31:28] <= data_in;
0: rtc_data_out_r[3:0] <= data_in_r;
1: rtc_data_out_r[7:4] <= data_in_r;
2: rtc_data_out_r[11:8] <= data_in_r;
3: rtc_data_out_r[15:12] <= data_in_r;
4: rtc_data_out_r[19:16] <= data_in_r;
5: rtc_data_out_r[23:20] <= data_in_r;
6: rtc_data_out_r[27:24] <= data_in_r;
7: rtc_data_out_r[31:28] <= data_in_r;
8: begin
rtc_data_out_r[35:32] <= (data_in < 10)
? data_in
: data_in - 10;
rtc_data_out_r[39:36] <= data_in < 10 ? 0 : 1;
rtc_data_out_r[35:32] <= (data_in_r < 10)
? data_in_r
: data_in_r - 10;
rtc_data_out_r[39:36] <= data_in_r < 10 ? 0 : 1;
end
9: rtc_data_out_r[43:40] <= data_in;
10: rtc_data_out_r[47:44] <= data_in;
9: rtc_data_out_r[43:40] <= data_in_r;
10: rtc_data_out_r[47:44] <= data_in_r;
11: begin
rtc_data_out_r[51:48] <= (data_in < 10)
? data_in
: data_in - 10;
rtc_data_out_r[55:52] <= data_in < 10 ? 1 : 2;
rtc_data_out_r[51:48] <= (data_in_r < 10)
? data_in_r
: data_in_r - 10;
rtc_data_out_r[55:52] <= data_in_r < 10 ? 1 : 2;
end
endcase
mode_r <= SRTC_WRITE2;
we_countdown_r <= 5;
we_countdown_r <= 4;
rtc_we_r <= 1;
end
end
endcase
endcase
end else if(reg_oe_falling && enable) begin
case (addr_in)
case (addr_in_r[0])
1'b0: // read data register
if(mode_r == SRTC_READ) begin
case(rtc_ptr)
@@ -164,18 +179,25 @@ always @(posedge clkin) begin
+ (rtc_data_r[55:52] << 1)
+ (rtc_data_r[55:52] << 3) - 10;
12: data_out_r <= rtc_data_r[59:56];
// 14: mode_r <= SRTC_IDLE;
15: begin
rtc_data_r <= rtc_data_in;
data_out_r <= 8'h0f;
end
default: data_out_r <= 8'h0f;
endcase
default: data_out_r <= 8'h0f;
endcase
rtc_ptr <= rtc_ptr == 13 ? 15 : rtc_ptr + 1;
end else begin
data_out_r <= 8'h00;
end
// 1'b1: // control register is write only
endcase
end else if(mode_r == SRTC_WRITE2) begin
we_countdown_r <= we_countdown_r - 1;
if (we_countdown_r == 3'b000) begin
mode_r <= SRTC_WRITE;
rtc_we_r <= 0;
end
end
end

View File

@@ -98,6 +98,9 @@ upd77c25_pgmrom pgmrom (
.doutb(pgm_doutb) // output [23 : 0] doutb
);
reg [7:0] DIr;
always @(posedge CLK) if(~nWR) DIr <= DI;
wire [23:0] opcode_w = pgm_doutb;
reg [1:0] op;
reg [1:0] op_pselect;
@@ -128,8 +131,8 @@ always @(posedge CLK) reg_nCS_sreg <= {reg_nCS_sreg[3:0], nCS};
reg [5:0] reg_oe_sreg;
initial reg_oe_sreg = 6'b111111;
always @(posedge CLK) reg_oe_sreg <= {reg_oe_sreg[4:0], nRD};
wire reg_oe_rising = !reg_nCS_sreg[4] && (reg_oe_sreg[5:0] == 6'b000001);
wire reg_oe_falling = (reg_oe_sreg[5:0] == 6'b100000);
wire reg_oe_rising = !reg_nCS_sreg[4] && (reg_oe_sreg[5:1] == 5'b00001);
wire reg_oe_falling = (reg_oe_sreg[5:1] == 5'b10000);
reg [4:0] reg_DP_nCS_sreg;
initial reg_DP_nCS_sreg = 5'b11111;
@@ -138,7 +141,7 @@ always @(posedge CLK) reg_DP_nCS_sreg <= {reg_DP_nCS_sreg[3:0], DP_nCS};
reg [5:0] reg_we_sreg;
initial reg_we_sreg = 6'b111111;
always @(posedge CLK) reg_we_sreg <= {reg_we_sreg[4:0], nWR};
wire reg_we_rising = !reg_nCS_sreg[4] && (reg_we_sreg[5:0] == 6'b000001);
wire reg_we_rising = !reg_nCS_sreg[4] && (reg_we_sreg[5:1] == 5'b00001);
wire [15:0] ram_douta;
wire [9:0] ram_addra;
@@ -303,12 +306,12 @@ always @(posedge CLK) begin
if(reg_we_rising && (A0r[3] == 1'b0)) begin
if(!regs_sr[SR_DRC]) begin
if(regs_sr[SR_DRS] == 1'b0) begin
regs_dr[7:0] <= DI;
regs_dr[7:0] <= DIr;
end else begin
regs_dr[15:8] <= DI;
regs_dr[15:8] <= DIr;
end
end else begin
regs_dr[7:0] <= DI;
regs_dr[7:0] <= DIr;
end
end else if(ld_dst == 4'b0110 && insn_state == STATE_STORE) begin
if (op == I_OP || op == I_RT) regs_dr <= idb;

View File

@@ -34,7 +34,9 @@ module address(
output msu_enable,
output cx4_enable,
output cx4_vect_enable,
output r213f_enable
output r213f_enable,
output snescmd_rd_enable,
output snescmd_wr_enable
);
wire [23:0] SRAM_SNES_ADDR;
@@ -54,23 +56,20 @@ assign ROM_ADDR = SRAM_SNES_ADDR;
assign ROM_SEL = 1'b0;
wire msu_enable_w = use_msu1 & (!SNES_ADDR[22] && ((SNES_ADDR[15:0] & 16'hfff8) == 16'h2000));
reg [5:0] msu_enable_r;
initial msu_enable_r = 6'b000000;
always @(posedge CLK) msu_enable_r <= {msu_enable_r[4:0], msu_enable_w};
assign msu_enable = &msu_enable_r[5:2];
assign msu_enable = msu_enable_w;
wire cx4_enable_w = (!SNES_ADDR[22] && (SNES_ADDR[15:13] == 3'b011));
reg [5:0] cx4_enable_r;
initial cx4_enable_r = 6'b000000;
always @(posedge CLK) cx4_enable_r <= {cx4_enable_r[4:0], cx4_enable_w};
assign cx4_enable = &cx4_enable_r[5:2];
assign cx4_enable = cx4_enable_w;
assign cx4_vect_enable = &SNES_ADDR[15:5];
wire r213f_enable_w = (SNES_PA == 8'h3f);
reg [5:0] r213f_enable_r;
initial r213f_enable_r = 6'b000000;
always @(posedge CLK) r213f_enable_r <= {r213f_enable_r[4:0], r213f_enable_w};
assign r213f_enable = &r213f_enable_r[5:2];
assign r213f_enable = r213f_enable_w;
wire snescmd_rd_enable_w = (SNES_PA[7:4] == 4'b1111);
assign snescmd_rd_enable = snescmd_rd_enable_w;
wire snescmd_wr_enable_w = (SNES_ADDR[23:4] == 20'hccccc);
assign snescmd_wr_enable = snescmd_wr_enable_w;
endmodule

View File

@@ -334,6 +334,7 @@ always @(posedge CLK) begin
CACHE_ST <= ST_CACHE_START;
cache_pgmpage <= cx4_mmio_pgmpage;
cache_cachepage <= cx4_mmio_cachepage;
cx4_busy[BUSY_CACHE] <= 1'b1;
end else if(cpu_cache_en
& (~cachevalid[~cpu_page]
| |(cachetag[~cpu_page] ^ cpu_p))) begin
@@ -431,7 +432,7 @@ end
/***************************
=========== CPU ===========
***************************/
reg [4:0] CPU_STATE;
reg [5:0] CPU_STATE;
reg [2:0] cpu_sp;
initial cpu_sp = 3'b000;
wire [15:0] cpu_op_w;
@@ -451,16 +452,19 @@ reg [23:0] cpu_dummy;
reg [23:0] cpu_tmp;
reg [23:0] cpu_sa; // tmp register for shifted accumulator
reg [7:0] cpu_wait;
initial cpu_wait = 8'h00;
wire [9:0] cx4_datrom_addr = cpu_a[9:0];
wire [23:0] cx4_datrom_do;
wire [7:0] cx4_datram_do;
parameter ST_CPU_IDLE = 5'b00001;
parameter ST_CPU_0 = 5'b00010;
parameter ST_CPU_1 = 5'b00100;
parameter ST_CPU_2 = 5'b01000;
parameter ST_CPU_3 = 5'b10000;
parameter ST_CPU_IDLE = 6'b000001;
parameter ST_CPU_0 = 6'b000010;
parameter ST_CPU_1 = 6'b000100;
parameter ST_CPU_2 = 6'b001000;
parameter ST_CPU_3 = 6'b010000;
parameter ST_CPU_4 = 6'b100000;
initial CPU_STATE = ST_CPU_IDLE;
@@ -636,7 +640,7 @@ always @(posedge CLK) begin
cpu_sp <= cpu_sp - 1;
end
OP_WAI: if(BUS_RDY) cpu_pc <= cpu_pc + 1;
OP_BUS: begin
OP_BUS: begin
cpu_bus_rq <= 1'b0;
cpu_pc <= cpu_pc + 1;
end
@@ -710,7 +714,6 @@ always @(posedge CLK) begin
endcase
end
ST_CPU_3: begin
CPU_STATE <= ST_CPU_0;
case(op)
OP_BUS: cpu_busaddr <= cpu_busaddr + 1;
OP_WRRAM: cx4_cpu_datram_we <= 1'b0;
@@ -747,6 +750,29 @@ always @(posedge CLK) begin
end
endcase
cpu_op <= cpu_op_w;
casex(cpu_op_w[15:11])
5'b00x01, 5'b00x10, 5'b00100, 5'b00111: begin
cpu_wait <= 8'h07;
CPU_STATE <= ST_CPU_4;
end
5'b01110, 5'b01101, 5'b11101: begin
cpu_wait <= 8'h03;
CPU_STATE <= ST_CPU_4;
end
/*5'b10011: begin
cpu_wait <= 8'h02;
CPU_STATE <= ST_CPU_4;
end
5'b01000: begin
cpu_wait <= 8'h0e;
CPU_STATE <= ST_CPU_4;
end*/
default: begin
cpu_wait <= 8'h00;
CPU_STATE <= ST_CPU_0;
end
endcase
casex(cpu_op_w[15:11])
5'b00000: op <= OP_NOP;
@@ -790,6 +816,11 @@ always @(posedge CLK) begin
op_param <= cpu_op_w[7:0];
op_sa <= cpu_op_w[9:8];
end
ST_CPU_4: begin
cpu_wait <= cpu_wait - 1;
if(cpu_wait) CPU_STATE <= ST_CPU_4;
else CPU_STATE <= ST_CPU_0;
end
endcase
end

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