173 lines
4.4 KiB
C
173 lines
4.4 KiB
C
/* sd2snes - SD card based universal cartridge for the SNES
|
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
|
AVR firmware portion
|
|
|
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
|
See sdcard.c|h, config.h.
|
|
|
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
|
see ff.c|h.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License only.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
snes.c: SNES hardware control and monitoring
|
|
*/
|
|
|
|
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
|
#include "bits.h"
|
|
#include "config.h"
|
|
#include "uart.h"
|
|
#include "snes.h"
|
|
#include "memory.h"
|
|
#include "fileops.h"
|
|
#include "ff.h"
|
|
#include "led.h"
|
|
#include "smc.h"
|
|
#include "timer.h"
|
|
#include "cli.h"
|
|
#include "fpga.h"
|
|
#include "fpga_spi.h"
|
|
|
|
uint8_t initloop=1;
|
|
uint32_t saveram_crc, saveram_crc_old;
|
|
extern snes_romprops_t romprops;
|
|
|
|
volatile int reset_changed;
|
|
|
|
void prepare_reset() {
|
|
set_mcu_ovr(1);
|
|
snes_reset(1);
|
|
delay_ms(1);
|
|
if(romprops.ramsize_bytes && fpga_test() == FPGA_TEST_TOKEN) {
|
|
writeled(1);
|
|
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
|
|
writeled(0);
|
|
}
|
|
rdyled(1);
|
|
readled(1);
|
|
writeled(1);
|
|
snes_reset(0);
|
|
while(get_snes_reset());
|
|
snes_reset(1);
|
|
delay_ms(200);
|
|
}
|
|
|
|
void snes_init() {
|
|
/* put reset level on reset pin */
|
|
BITBAND(SNES_RESET_REG->FIOCLR, SNES_RESET_BIT) = 1;
|
|
/* reset the SNES */
|
|
snes_reset(1);
|
|
}
|
|
|
|
/*
|
|
* sets the SNES reset state.
|
|
*
|
|
* state: put SNES in reset state when 1, release when 0
|
|
*/
|
|
void snes_reset(int state) {
|
|
BITBAND(SNES_RESET_REG->FIODIR, SNES_RESET_BIT) = state;
|
|
}
|
|
|
|
/*
|
|
* gets the SNES reset state.
|
|
*
|
|
* returns: 1 when reset, 0 when not reset
|
|
*/
|
|
uint8_t get_snes_reset() {
|
|
return !BITBAND(SNES_RESET_REG->FIOPIN, SNES_RESET_BIT);
|
|
}
|
|
|
|
/*
|
|
* SD2SNES main loop.
|
|
* monitors SRAM changes and other things
|
|
*/
|
|
uint32_t diffcount = 0, samecount = 0, didnotsave = 0;
|
|
uint8_t sram_valid = 0;
|
|
void snes_main_loop() {
|
|
if(!romprops.ramsize_bytes)return;
|
|
if(initloop) {
|
|
saveram_crc_old = calc_sram_crc(SRAM_SAVE_ADDR, romprops.ramsize_bytes);
|
|
initloop=0;
|
|
}
|
|
saveram_crc = calc_sram_crc(SRAM_SAVE_ADDR, romprops.ramsize_bytes);
|
|
sram_valid = sram_reliable();
|
|
if(crc_valid && sram_valid) {
|
|
if(saveram_crc != saveram_crc_old) {
|
|
if(samecount) {
|
|
diffcount=1;
|
|
} else {
|
|
diffcount++;
|
|
didnotsave++;
|
|
}
|
|
samecount=0;
|
|
}
|
|
if(saveram_crc == saveram_crc_old) {
|
|
samecount++;
|
|
}
|
|
if(diffcount>=1 && samecount==5) {
|
|
printf("SaveRAM CRC: 0x%04lx; saving\n", saveram_crc);
|
|
writeled(1);
|
|
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
|
|
writeled(0);
|
|
didnotsave=0;
|
|
}
|
|
if(didnotsave>50) {
|
|
printf("periodic save (sram contents keep changing...)\n");
|
|
diffcount=0;
|
|
writeled(1);
|
|
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
|
|
didnotsave=0;
|
|
writeled(0);
|
|
}
|
|
saveram_crc_old = saveram_crc;
|
|
}
|
|
printf("crc=%lx crc_valid=%d sram_valid=%d diffcount=%ld samecount=%ld, didnotsave=%ld\n", saveram_crc, crc_valid, sram_valid, diffcount, samecount, didnotsave);
|
|
}
|
|
|
|
/*
|
|
* SD2SNES menu loop.
|
|
* monitors menu selection. return when selection was made.
|
|
*/
|
|
uint8_t menu_main_loop() {
|
|
uint8_t cmd = 0;
|
|
sram_writebyte(0, SRAM_CMD_ADDR);
|
|
while(!cmd) {
|
|
if(!get_snes_reset()) {
|
|
while(!sram_reliable())printf("hurr\n");
|
|
cmd = sram_readbyte(SRAM_CMD_ADDR);
|
|
}
|
|
if(get_snes_reset()) {
|
|
cmd = 0;
|
|
}
|
|
sleep_ms(20);
|
|
cli_entrycheck();
|
|
}
|
|
return cmd;
|
|
}
|
|
|
|
void get_selected_name(uint8_t* fn) {
|
|
uint32_t addr;
|
|
addr = sram_readlong(SRAM_PARAM_ADDR);
|
|
printf("fd addr=%lx\n", addr);
|
|
sram_readblock(fn, addr + 7 + SRAM_MENU_ADDR, 256);
|
|
}
|
|
|
|
void snes_bootprint(void* msg) {
|
|
set_mcu_ovr(1);
|
|
sram_writeblock(msg, SRAM_CMD_ADDR, 33);
|
|
set_mcu_ovr(0);
|
|
delay_ms(30);
|
|
set_mcu_ovr(1);
|
|
}
|