123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- /* sd2snes - SD card based universal cartridge for the SNES
- Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
- AVR firmware portion
- Inspired by and based on code from sd2iec, written by Ingo Korb et al.
- See sdcard.c|h, config.h.
- FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
- see ff.c|h.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License only.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- fpga_spi.h: functions for SPI ctrl, SRAM interfacing and feature configuration
- */
- /*
- SPI commands
- cmd param function
- =============================================
- 0t bbhhll set address to 0xbbhhll
- t = target
- target: 0 = RAM
- 1 = MSU Audio buffer
- 2 = MSU Data buffer
- targets 1 & 2 only require 2 address bytes to
- be written.
- 10 bbhhll set SNES input address mask to 0xbbhhll
- 20 bbhhll set SRAM address mask to 0xbbhhll
- 3m - set mapper to m
- 0=HiROM, 1=LoROM, 2=ExHiROM, 6=SF96, 7=Menu
- 4s - trigger SD DMA (512b from SD to memory)
- s: Bit 2 = partial, Bit 1:0 = target
- target: see above
- 60 sssseeee set SD DMA partial transfer start+end
- ssss = start offset (msb first)
- eeee = end offset (msb first)
- 8p - read (RAM only)
- p: 0 = no increment after read
- 8 = increment after read
- 9p {xx}* write xx
- p: i-tt
- tt = target (see above)
- i = increment (see above)
- E0 ssrr set MSU-1 status register (=FPGA status [7:0])
- ss = bits to set in status register (1=set)
- rr = bits to reset in status register (1=reset)
- E1 - pause DAC
- E2 - resume/play DAC
- E3 - reset DAC playback pointer (0)
- E4 hhll set MSU read pointer
- E5 tt{7} set RTC (SPC7110 format + 1000s of year,
- nibbles packed)
- eg 0x20111210094816 is 2011-12-10, 9:48:16
- E6 ssrr set/reset BS-X status register [7:0]
- E7 - reset SRTC state
- E8 - reset DSP program and data ROM write pointers
- E9 hhmmllxxxx write+incr. DSP program ROM (xxxx=dummy writes)
- EA hhllxxxx write+incr. DSP data ROM (xxxx=dummy writes)
- EB - put DSP into reset
- EC - release DSP from reset
- ED - set feature enable bits (see below)
- F0 - receive test token (to see if FPGA is alive)
- F1 - receive status (16bit, MSB first), see below
- F2 - get MSU data address (32bit, MSB first)
- F3 - get MSU audio track no. (16bit, MSB first)
- F4 - get MSU volume (8bit)
- FE - get SNES master clock frequency (32bit, MSB first)
- measured 1x/sec
- FF {xx}* echo (returns the sent data in the next byte)
- FPGA status word:
- bit function
- ==========================================================================
- 15 SD DMA busy (0=idle, 1=busy)
- 14 DAC read pointer MSB
- 13 MSU read pointer MSB
- 12 [TODO SD DMA CRC status (0=ok, 1=error); valid after bit 15 -> 0]
- 11 reserved (0)
- 10 reserved (0)
- 9 reserved (0)
- 8 reserved (0)
- 7 reserved (0)
- 6 reserved (0)
- 5 MSU1 Audio request from SNES
- 4 MSU1 Data request from SNES
- 3 reserved (0)
- 2 MSU1 Audio control status: 0=no repeat, 1=repeat
- 1 MSU1 Audio control status: 0=pause, 1=play
- 0 MSU1 Audio control request
- FPGA feature enable bits:
- bit function
- ==========================================================================
- 7 -
- 6 -
- 5 -
- 4 -
- 3 enable MSU1 registers
- 2 enable SRTC registers
- 1 enable ST0010 mapping
- 0 enable DSPx mapping
- */
- #include <arm/NXP/LPC17xx/LPC17xx.h>
- #include "bits.h"
- #include "fpga.h"
- #include "config.h"
- #include "uart.h"
- #include "spi.h"
- #include "fpga_spi.h"
- #include "timer.h"
- void fpga_spi_init(void) {
- spi_init(SPI_SPEED_FPGA_FAST);
- }
- void set_msu_addr(uint16_t address) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0x02);
- FPGA_TX_BYTE((address>>8)&0xff);
- FPGA_TX_BYTE((address)&0xff);
- FPGA_DESELECT();
- }
- void set_dac_addr(uint16_t address) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0x01);
- FPGA_TX_BYTE((address>>8)&0xff);
- FPGA_TX_BYTE((address)&0xff);
- FPGA_DESELECT();
- }
- void set_mcu_addr(uint32_t address) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0x00);
- FPGA_TX_BYTE((address>>16)&0xff);
- FPGA_TX_BYTE((address>>8)&0xff);
- FPGA_TX_BYTE((address)&0xff);
- FPGA_DESELECT();
- }
- void set_saveram_mask(uint32_t mask) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0x20);
- FPGA_TX_BYTE((mask>>16)&0xff);
- FPGA_TX_BYTE((mask>>8)&0xff);
- FPGA_TX_BYTE((mask)&0xff);
- FPGA_DESELECT();
- }
- void set_rom_mask(uint32_t mask) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0x10);
- FPGA_TX_BYTE((mask>>16)&0xff);
- FPGA_TX_BYTE((mask>>8)&0xff);
- FPGA_TX_BYTE((mask)&0xff);
- FPGA_DESELECT();
- }
- void set_mapper(uint8_t val) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0x30 | (val & 0x0f));
- FPGA_DESELECT();
- }
- uint8_t fpga_test() {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xF0); /* TEST */
- FPGA_TX_BYTE(0x00); /* dummy */
- uint8_t result = FPGA_RX_BYTE();
- FPGA_DESELECT();
- return result;
- }
- uint16_t fpga_status() {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xF1); /* STATUS */
- FPGA_TX_BYTE(0x00); /* dummy */
- uint16_t result = (FPGA_RX_BYTE()) << 8;
- result |= FPGA_RX_BYTE();
- FPGA_DESELECT();
- return result;
- }
- void fpga_set_sddma_range(uint16_t start, uint16_t end) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0x60); /* DMA_RANGE */
- FPGA_TX_BYTE(start>>8);
- FPGA_TX_BYTE(start&0xff);
- FPGA_TX_BYTE(end>>8);
- FPGA_TX_BYTE(end&0xff);
- //if(tgt==1 && (test=FPGA_RX_BYTE()) != 0x41) printf("!!!!!!!!!!!!!!! -%02x- \n", test);
- FPGA_DESELECT();
- }
- void fpga_sddma(uint8_t tgt, uint8_t partial) {
- uint32_t test = 0;
- uint8_t status = 0;
- BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 0;
- FPGA_SELECT();
- FPGA_TX_BYTE(0x40 | (tgt & 0x3) | ((partial & 1) << 2) ); /* DO DMA */
- FPGA_TX_BYTE(0x00); /* dummy for falling DMA_EN edge */
- //if(tgt==1 && (test=FPGA_RX_BYTE()) != 0x41) printf("!!!!!!!!!!!!!!! -%02x- \n", test);
- FPGA_DESELECT();
- FPGA_SELECT();
- FPGA_TX_BYTE(0xF1); /* STATUS */
- FPGA_TX_BYTE(0x00); /* dummy */
- while((status=FPGA_RX_BYTE()) & 0x80) {
- FPGA_RX_BYTE(); /* eat the 2nd status byte */
- test++;
- }
- FPGA_DESELECT();
- if(test<5)printf("loopy: %ld %02x\n", test, status);
- BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1;
- }
- void set_dac_vol(uint8_t volume) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0x50);
- FPGA_TX_BYTE(volume);
- FPGA_TX_BYTE(0x00); /* latch rise */
- FPGA_TX_BYTE(0x00); /* latch fall */
- FPGA_DESELECT();
- }
- void dac_play() {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xe2);
- FPGA_TX_BYTE(0x00); /* latch reset */
- FPGA_DESELECT();
- }
- void dac_pause() {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xe1);
- FPGA_TX_BYTE(0x00); /* latch reset */
- FPGA_DESELECT();
- }
- void dac_reset() {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xe3);
- FPGA_TX_BYTE(0x00); /* latch reset */
- FPGA_TX_BYTE(0x00); /* latch reset */
- FPGA_DESELECT();
- }
- void msu_reset(uint16_t address) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xe4);
- FPGA_TX_BYTE((address>>8) & 0xff); /* address hi */
- FPGA_TX_BYTE(address & 0xff); /* address lo */
- FPGA_TX_BYTE(0x00); /* latch reset */
- FPGA_TX_BYTE(0x00); /* latch reset */
- FPGA_DESELECT();
- }
- void set_msu_status(uint8_t set, uint8_t reset) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xe0);
- FPGA_TX_BYTE(set);
- FPGA_TX_BYTE(reset);
- FPGA_TX_BYTE(0x00); /* latch reset */
- FPGA_DESELECT();
- }
- uint8_t get_msu_volume() {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xF4); /* MSU_VOLUME */
- FPGA_TX_BYTE(0x00); /* dummy */
- uint8_t result = FPGA_RX_BYTE();
- FPGA_DESELECT();
- return result;
- }
- uint16_t get_msu_track() {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xF3); /* MSU_TRACK */
- FPGA_TX_BYTE(0x00); /* dummy */
- uint16_t result = (FPGA_RX_BYTE()) << 8;
- result |= FPGA_RX_BYTE();
- FPGA_DESELECT();
- return result;
- }
- uint32_t get_msu_offset() {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xF2); /* MSU_OFFSET */
- FPGA_TX_BYTE(0x00); /* dummy */
- uint32_t result = (FPGA_RX_BYTE()) << 24;
- result |= (FPGA_RX_BYTE()) << 16;
- result |= (FPGA_RX_BYTE()) << 8;
- result |= (FPGA_RX_BYTE());
- FPGA_DESELECT();
- return result;
- }
- uint32_t get_snes_sysclk() {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xFE); /* GET_SYSCLK */
- FPGA_TX_BYTE(0x00); /* dummy */
- FPGA_TX_BYTE(0x00); /* dummy */
- uint32_t result = (FPGA_RX_BYTE()) << 24;
- result |= (FPGA_RX_BYTE()) << 16;
- result |= (FPGA_RX_BYTE()) << 8;
- result |= (FPGA_RX_BYTE());
- FPGA_DESELECT();
- return result;
- }
- void set_bsx_regs(uint8_t set, uint8_t reset) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xe6);
- FPGA_TX_BYTE(set);
- FPGA_TX_BYTE(reset);
- FPGA_TX_BYTE(0x00); /* latch reset */
- FPGA_DESELECT();
- }
- void set_fpga_time(uint64_t time) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xe5);
- FPGA_TX_BYTE((time >> 48) & 0xff);
- FPGA_TX_BYTE((time >> 40) & 0xff);
- FPGA_TX_BYTE((time >> 32) & 0xff);
- FPGA_TX_BYTE((time >> 24) & 0xff);
- FPGA_TX_BYTE((time >> 16) & 0xff);
- FPGA_TX_BYTE((time >> 8) & 0xff);
- FPGA_TX_BYTE(time & 0xff);
- FPGA_TX_BYTE(0x00);
- FPGA_DESELECT();
- }
- void fpga_reset_srtc_state() {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xe7);
- FPGA_TX_BYTE(0x00);
- FPGA_TX_BYTE(0x00);
- FPGA_DESELECT();
- }
- void fpga_reset_dspx_addr() {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xe8);
- FPGA_TX_BYTE(0x00);
- FPGA_TX_BYTE(0x00);
- FPGA_DESELECT();
- }
- void fpga_write_dspx_pgm(uint32_t data) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xe9);
- FPGA_TX_BYTE((data>>16)&0xff);
- FPGA_TX_BYTE((data>>8)&0xff);
- FPGA_TX_BYTE((data)&0xff);
- FPGA_TX_BYTE(0x00);
- FPGA_TX_BYTE(0x00);
- FPGA_DESELECT();
- }
- void fpga_write_dspx_dat(uint16_t data) {
- FPGA_SELECT();
- FPGA_TX_BYTE(0xea);
- FPGA_TX_BYTE((data>>8)&0xff);
- FPGA_TX_BYTE((data)&0xff);
- FPGA_TX_BYTE(0x00);
- FPGA_TX_BYTE(0x00);
- FPGA_DESELECT();
- }
- void fpga_dspx_reset(uint8_t reset) {
- FPGA_SELECT();
- FPGA_TX_BYTE(reset ? 0xeb : 0xec);
- FPGA_TX_BYTE(0x00);
- FPGA_DESELECT();
- }
- void fpga_set_features(uint8_t feat) {
- printf("set features: %02x\n", feat);
- FPGA_SELECT();
- FPGA_TX_BYTE(0xed);
- FPGA_TX_BYTE(feat);
- FPGA_DESELECT();
- }
|