123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- /* sd2snes - SD card based universal cartridge for the SNES
- 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.
- 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 xsssyeee set SD DMA partial transfer parameters
- x: 0 = read from sector start (skip until
- start offset reached)
- 8 = assume mid-sector position and read
- immediately
- sss = start offset (msb first)
- y: 0 = skip rest of SD sector
- 8 = stop mid-sector if end offset reached
- eee = end offset (msb first)
- 8p - read (RAM only)
- p: 0 = no increment after read
- 8 = increment after read
- 9p {xx}* write xx
- p: i-tt
- tt = target (see above)
- i = increment (see above)
- E0 ssrr set MSU-1 status register (=FPGA status [7:0])
- ss = bits to set in status register (1=set)
- rr = bits to reset in status register (1=reset)
- E1 - pause DAC
- E2 - resume/play DAC
- E3 - reset DAC playback pointer (0)
- E4 hhll set MSU read pointer
- E5 tt{7} set RTC (SPC7110 format + 1000s of year,
- nibbles packed)
- eg 0x20111210094816 is 2011-12-10, 9:48:16
- E6 ssrr set/reset BS-X status register [7:0]
- E7 - reset SRTC state
- E8 - reset DSP program and data ROM write pointers
- E9 hhmmllxxxx write+incr. DSP program ROM (xxxx=dummy writes)
- EA hhllxxxx write+incr. DSP data ROM (xxxx=dummy writes)
- EB - put DSP into reset
- EC - release DSP from reset
- ED - set feature enable bits (see below)
- EE - set $213f override value (0=NTSC, 1=PAL)
- 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 reserved (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 enable $213F override
- 3 enable MSU1 registers
- 2 enable SRTC registers
- 1 enable ST0010 mapping
- 0 enable DSPx mapping
- */
- #include <arm/NXP/LPC17xx/LPC17xx.h>
- #include "bits.h"
- #include "fpga.h"
- #include "config.h"
- #include "uart.h"
- #include "spi.h"
- #include "fpga_spi.h"
- #include "timer.h"
- #include "sdnative.h"
- void fpga_spi_init( void )
- {
- spi_init();
- BITBAND( FPGA_MCU_RDY_REG->FIODIR, FPGA_MCU_RDY_BIT ) = 0;
- }
- void set_msu_addr( uint16_t address )
- {
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_SETADDR | FPGA_TGT_MSUBUF );
- 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( FPGA_CMD_SETADDR | FPGA_TGT_DACBUF );
- 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( FPGA_CMD_SETADDR | FPGA_TGT_MEM );
- 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( FPGA_CMD_SETRAMMASK );
- 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( FPGA_CMD_SETROMMASK );
- 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( FPGA_CMD_SETMAPPER( val ) );
- FPGA_DESELECT();
- }
- uint8_t fpga_test()
- {
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_TEST );
- uint8_t result = FPGA_RX_BYTE();
- FPGA_DESELECT();
- return result;
- }
- uint16_t fpga_status()
- {
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_GETSTATUS );
- 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 )
- {
- printf( "%s %08X -> %08X\n", __func__, start, end );
- FPGA_SELECT();
- 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 );
- FPGA_DESELECT();
- }
- void fpga_sddma( uint8_t tgt, uint8_t partial )
- {
- //printf("%s %02X -> %02X\n", __func__, tgt, partial);
- //uint32_t test = 0;
- //uint8_t status = 0;
- BITBAND( SD_CLKREG->FIODIR, SD_CLKPIN ) = 0;
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_SDDMA | ( tgt & 3 ) | ( partial ? FPGA_SDDMA_PARTIAL : 0 ) );
- FPGA_TX_BYTE( 0x00 ); /* dummy for falling DMA_EN edge */
- FPGA_DESELECT();
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_GETSTATUS );
- DBG_SD printf( "FPGA DMA request sent, wait for completion..." );
- while ( FPGA_RX_BYTE() & 0x80 )
- {
- FPGA_RX_BYTE(); /* eat the 2nd status byte */
- }
- DBG_SD printf( "...complete\n" );
- FPGA_DESELECT();
- BITBAND( SD_CLKREG->FIODIR, SD_CLKPIN ) = 1;
- }
- void dac_play()
- {
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_DACPLAY );
- FPGA_TX_BYTE( 0x00 ); /* latch reset */
- FPGA_DESELECT();
- }
- void dac_pause()
- {
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_DACPAUSE );
- FPGA_TX_BYTE( 0x00 ); /* latch reset */
- FPGA_DESELECT();
- }
- void dac_reset()
- {
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_DACRESETPTR );
- 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( FPGA_CMD_MSUSETPTR );
- 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( FPGA_CMD_MSUSETBITS );
- FPGA_TX_BYTE( set );
- FPGA_TX_BYTE( reset );
- FPGA_TX_BYTE( 0x00 ); /* latch reset */
- FPGA_DESELECT();
- }
- uint16_t get_msu_track()
- {
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_MSUGETTRACK );
- 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( FPGA_CMD_MSUGETADDR );
- 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( 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;
- result |= ( FPGA_RX_BYTE() );
- FPGA_DESELECT();
- return result;
- }
- void set_bsx_regs( uint8_t set, uint8_t reset )
- {
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_BSXSETBITS );
- 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( FPGA_CMD_RTCSET );
- 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( FPGA_CMD_SRTCRESET );
- FPGA_TX_BYTE( 0x00 );
- FPGA_TX_BYTE( 0x00 );
- FPGA_DESELECT();
- }
- void fpga_reset_dspx_addr()
- {
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_DSPRESETPTR );
- FPGA_TX_BYTE( 0x00 );
- FPGA_TX_BYTE( 0x00 );
- FPGA_DESELECT();
- }
- void fpga_write_dspx_pgm( uint32_t data )
- {
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_DSPWRITEPGM );
- 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( FPGA_CMD_DSPWRITEDAT );
- 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 ? FPGA_CMD_DSPRESET : FPGA_CMD_DSPUNRESET );
- FPGA_TX_BYTE( 0x00 );
- FPGA_DESELECT();
- }
- void fpga_set_features( uint8_t feat )
- {
- printf( "set features: %02x\n", feat );
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_SETFEATURE );
- FPGA_TX_BYTE( feat );
- FPGA_DESELECT();
- }
- void fpga_set_213f( uint8_t data )
- {
- printf( "set 213f: %d\n", data );
- FPGA_SELECT();
- FPGA_TX_BYTE( FPGA_CMD_SET213F );
- FPGA_TX_BYTE( data );
- FPGA_DESELECT();
- }
|