/* sd2snes - SD card based universal cartridge for the SNES Copyright (C) 2009-2010 Maximilian Rehkopf AVR firmware portion Inspired by and based on code from sd2iec, written by Ingo Korb et al. See sdcard.c|h, config.h. FAT file system access based on code by ChaN, Jim Brain, Ingo Korb, see ff.c|h. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License only. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA fpga.c: FPGA (re)configuration */ /* FPGA pin mapping ================ CCLK P0.11 out PROG_B P1.15 out INIT_B P2.9 in DIN P2.8 out DONE P0.22 in */ #include #include "bits.h" #include "fpga.h" #include "fpga_spi.h" #include "config.h" #include "uart.h" #include "diskio.h" #include "integer.h" #include "ff.h" #include "fileops.h" #include "spi.h" #include "led.h" #include "timer.h" #include "rle.h" #include "cfgware.h" void fpga_set_prog_b( uint8_t val ) { if ( val ) { BITBAND( PROGBREG->FIOSET, PROGBBIT ) = 1; } else { BITBAND( PROGBREG->FIOCLR, PROGBBIT ) = 1; } } void fpga_set_cclk( uint8_t val ) { if ( val ) { BITBAND( CCLKREG->FIOSET, CCLKBIT ) = 1; } else { BITBAND( CCLKREG->FIOCLR, CCLKBIT ) = 1; } } int fpga_get_initb() { return BITBAND( INITBREG->FIOPIN, INITBBIT ); } void fpga_init() { /* mainly GPIO directions */ BITBAND( CCLKREG->FIODIR, CCLKBIT ) = 1; /* CCLK */ BITBAND( DONEREG->FIODIR, DONEBIT ) = 0; /* DONE */ BITBAND( PROGBREG->FIODIR, PROGBBIT ) = 1; /* PROG_B */ BITBAND( DINREG->FIODIR, DINBIT ) = 1; /* DIN */ BITBAND( INITBREG->FIODIR, INITBBIT ) = 0; /* INIT_B */ LPC_GPIO2->FIOMASK1 = 0; SPI_OFFLOAD = 0; fpga_set_cclk( 0 ); /* initial clk=0 */ } int fpga_get_done( void ) { return BITBAND( DONEREG->FIOPIN, DONEBIT ); } void fpga_postinit() { LPC_GPIO2->FIOMASK1 = 0; } void fpga_pgm( uint8_t *filename ) { int MAXRETRIES = 10; int retries = MAXRETRIES; uint8_t data; int i; tick_t timeout; do { i = 0; timeout = getticks() + 100; fpga_set_prog_b( 0 ); if ( BITBAND( PROGBREG->FIOPIN, PROGBBIT ) ) { printf( "PROGB is stuck high!\n" ); led_panic(); } 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(); } }; if ( fpga_get_done() ) { printf( "DONE is stuck high!\n" ); led_panic(); } LPC_GPIO2->FIOMASK1 = ~( BV( 0 ) ); uart_putc( 'p' ); /* open configware file */ file_open( filename, FA_READ ); if ( file_res ) { uart_putc( '?' ); uart_putc( 0x30 + file_res ); return; } uart_putc( 'C' ); for ( ;; ) { data = rle_file_getc(); i++; if ( file_status || file_res ) { break; /* error or eof */ } FPGA_SEND_BYTE_SERIAL( data ); } uart_putc( 'c' ); file_close(); printf( "fpga_pgm: %d bytes programmed\n", i ); delay_ms( 1 ); } while ( !fpga_get_done() && retries-- ); if ( !fpga_get_done() ) { printf( "FPGA failed to configure after %d tries.\n", MAXRETRIES ); led_panic(); } printf( "FPGA configured\n" ); fpga_postinit(); } void fpga_rompgm() { int MAXRETRIES = 10; int retries = MAXRETRIES; uint8_t data; int i; tick_t timeout; do { i = 0; timeout = getticks() + 100; fpga_set_prog_b( 0 ); uart_putc( 'P' ); fpga_set_prog_b( 1 ); while ( !fpga_get_initb() ) { if ( getticks() > timeout ) { printf( "no response from FPGA trying to initiate configuration!\n" ); led_panic(); } }; if ( fpga_get_done() ) { printf( "DONE is stuck high!\n" ); led_panic(); } LPC_GPIO2->FIOMASK1 = ~( BV( 0 ) ); uart_putc( 'p' ); /* open configware file */ rle_mem_init( cfgware, sizeof( cfgware ) ); printf( "sizeof(cfgware) = %d\n", sizeof( cfgware ) ); for ( ;; ) { data = rle_mem_getc(); if ( rle_state ) { break; } i++; FPGA_SEND_BYTE_SERIAL( data ); } uart_putc( 'c' ); printf( "fpga_pgm: %d bytes programmed\n", i ); delay_ms( 1 ); } while ( !fpga_get_done() && retries-- ); if ( !fpga_get_done() ) { printf( "FPGA failed to configure after %d tries.\n", MAXRETRIES ); led_panic(); } printf( "FPGA configured\n" ); fpga_postinit(); }