mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 07:06:52 +01:00
libsc64 start
This commit is contained in:
parent
790f30ae20
commit
e3b9008abb
@ -19,7 +19,7 @@
|
||||
#
|
||||
# Quartus Prime
|
||||
# Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition
|
||||
# Date created = 00:41:07 March 01, 2021
|
||||
# Date created = 23:48:45 March 10, 2021
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
|
@ -23,7 +23,7 @@ module cart_control (
|
||||
output reg o_eeprom_enable,
|
||||
output reg o_eeprom_16k_mode,
|
||||
|
||||
output reg o_n64_reset_btn,
|
||||
inout [7:0] io_gpio,
|
||||
|
||||
input i_debug_ready,
|
||||
|
||||
@ -57,7 +57,7 @@ module cart_control (
|
||||
localparam [3:0] REG_USB_DMA_ADDR = 4'd5;
|
||||
localparam [3:0] REG_USB_DMA_LEN = 4'd6;
|
||||
localparam [3:0] REG_DDIPL_ADDR = 4'd7;
|
||||
localparam [3:0] REG_SRAM_ADDR = 4'd8;
|
||||
localparam [3:0] REG_SAVE_ADDR = 4'd8;
|
||||
|
||||
localparam [10:0] MEM_USB_FIFO_BASE = 11'h400;
|
||||
|
||||
@ -77,6 +77,11 @@ module cart_control (
|
||||
|
||||
reg [15:0] r_bootloader;
|
||||
reg r_skip_bootloader;
|
||||
reg r_sram_768k_mode;
|
||||
reg [7:0] r_gpio_o;
|
||||
reg [7:0] r_gpio_i;
|
||||
reg [7:0] r_gpio_dir;
|
||||
reg [7:0] r_gpio_od;
|
||||
|
||||
|
||||
// Bus controller
|
||||
@ -104,7 +109,6 @@ module cart_control (
|
||||
o_eeprom_pi_enable <= 1'b0;
|
||||
o_eeprom_enable <= 1'b0;
|
||||
o_eeprom_16k_mode <= 1'b0;
|
||||
o_n64_reset_btn <= 1'b1;
|
||||
o_ddipl_address <= 24'hEF_8000;
|
||||
o_save_address <= 24'hFF_8000;
|
||||
o_debug_dma_bank <= 4'd1;
|
||||
@ -112,22 +116,27 @@ module cart_control (
|
||||
o_debug_dma_length <= 20'd0;
|
||||
r_bootloader <= 16'h0000;
|
||||
r_skip_bootloader <= 1'b0;
|
||||
r_sram_768k_mode <= 1'b0;
|
||||
r_gpio_o <= 8'h00;
|
||||
r_gpio_dir <= 8'h00;
|
||||
r_gpio_od <= 8'h00;
|
||||
end else begin
|
||||
if (i_request && i_write && !o_busy) begin
|
||||
case (i_address[3:0])
|
||||
REG_SCR: begin
|
||||
{
|
||||
r_skip_bootloader,
|
||||
o_flashram_enable,
|
||||
o_sram_enable,
|
||||
o_sd_enable,
|
||||
o_flashram_enable,
|
||||
r_sram_768k_mode,
|
||||
o_sram_enable,
|
||||
o_eeprom_pi_enable,
|
||||
o_eeprom_16k_mode,
|
||||
o_eeprom_enable,
|
||||
o_ddipl_enable,
|
||||
o_rom_switch,
|
||||
o_sdram_writable
|
||||
} <= {i_data[10:9], i_data[7:0]};
|
||||
o_sdram_writable,
|
||||
o_rom_switch
|
||||
} <= i_data[10:0];
|
||||
end
|
||||
|
||||
REG_BOOT: begin
|
||||
@ -135,7 +144,7 @@ module cart_control (
|
||||
end
|
||||
|
||||
REG_GPIO: begin
|
||||
o_n64_reset_btn <= ~i_data[0];
|
||||
{r_gpio_od, r_gpio_dir, r_gpio_o} <= {i_data[31:16], i_data[7:0]};
|
||||
end
|
||||
|
||||
REG_USB_SCR: begin
|
||||
@ -154,7 +163,7 @@ module cart_control (
|
||||
o_ddipl_address <= i_data[25:2];
|
||||
end
|
||||
|
||||
REG_SRAM_ADDR: begin
|
||||
REG_SAVE_ADDR: begin
|
||||
o_save_address <= i_data[25:2];
|
||||
end
|
||||
|
||||
@ -165,7 +174,6 @@ module cart_control (
|
||||
if (!r_reset_ff2 || !r_nmi_ff2) begin
|
||||
o_sdram_writable <= 1'b0;
|
||||
o_rom_switch <= r_skip_bootloader;
|
||||
o_n64_reset_btn <= 1'b1;
|
||||
o_debug_fifo_flush <= 1'b1;
|
||||
end
|
||||
end
|
||||
@ -185,16 +193,16 @@ module cart_control (
|
||||
REG_SCR: begin
|
||||
o_data[10:0] <= {
|
||||
r_skip_bootloader,
|
||||
o_flashram_enable,
|
||||
1'b0,
|
||||
o_sram_enable,
|
||||
o_sd_enable,
|
||||
o_flashram_enable,
|
||||
r_sram_768k_mode,
|
||||
o_sram_enable,
|
||||
o_eeprom_pi_enable,
|
||||
o_eeprom_16k_mode,
|
||||
o_eeprom_enable,
|
||||
o_ddipl_enable,
|
||||
o_rom_switch,
|
||||
o_sdram_writable
|
||||
o_sdram_writable,
|
||||
o_rom_switch
|
||||
};
|
||||
end
|
||||
|
||||
@ -207,7 +215,7 @@ module cart_control (
|
||||
end
|
||||
|
||||
REG_GPIO: begin
|
||||
o_data[2:0] <= {r_nmi_ff2, r_reset_ff2, ~o_n64_reset_btn};
|
||||
o_data[31:0] <= {r_gpio_od, r_gpio_dir, io_gpio, r_gpio_o};
|
||||
end
|
||||
|
||||
REG_USB_SCR: begin
|
||||
@ -218,7 +226,7 @@ module cart_control (
|
||||
o_data[25:0] <= {o_ddipl_address, 2'b00};
|
||||
end
|
||||
|
||||
REG_SRAM_ADDR: begin
|
||||
REG_SAVE_ADDR: begin
|
||||
o_data[25:0] <= {o_save_address, 2'b00};
|
||||
end
|
||||
|
||||
@ -231,4 +239,17 @@ module cart_control (
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// GPIO logic
|
||||
|
||||
always @(*) begin
|
||||
for (integer i = 0; i < 8; i = i + 1) begin
|
||||
if (r_gpio_dir[i] && (!r_gpio_od[i] || (r_gpio_od[i] && !r_gpio_o[i]))) begin
|
||||
io_gpio[i] = r_gpio_o[i];
|
||||
end else begin
|
||||
io_gpio[i] = 1'bZ;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -54,19 +54,19 @@ module n64_bank_decoder (
|
||||
o_prefetch <= 1'b0;
|
||||
end
|
||||
|
||||
16'b0001111000000001: begin // EEPROM
|
||||
if (i_eeprom_pi_enable) begin
|
||||
o_bank <= `BANK_EEPROM;
|
||||
end
|
||||
end
|
||||
|
||||
16'b0001111000000010: begin // SD
|
||||
16'b0001111000000001: begin // SD
|
||||
if (i_sd_enable) begin
|
||||
o_bank <= `BANK_SD;
|
||||
o_prefetch <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
16'b0001111000000011: begin // EEPROM
|
||||
if (i_eeprom_pi_enable) begin
|
||||
o_bank <= `BANK_EEPROM;
|
||||
end
|
||||
end
|
||||
|
||||
default: begin end
|
||||
endcase
|
||||
end
|
||||
|
@ -51,11 +51,7 @@ module top (
|
||||
|
||||
// Temporary signal names
|
||||
|
||||
wire w_n64_reset_btn;
|
||||
|
||||
assign {o_rtc_scl, io_rtc_sda} = 2'bZZ;
|
||||
assign io_pmod[3] = w_n64_reset_btn ? 1'bZ : 1'b0;
|
||||
assign {io_pmod[7:4], io_pmod[2:0]} = 7'bZZZZZZZ;
|
||||
|
||||
|
||||
// PLL clock generator
|
||||
@ -345,7 +341,7 @@ module top (
|
||||
.o_eeprom_enable(w_eeprom_enable),
|
||||
.o_eeprom_16k_mode(w_eeprom_16k_mode),
|
||||
|
||||
.o_n64_reset_btn(w_n64_reset_btn),
|
||||
.io_gpio(io_pmod),
|
||||
|
||||
.i_debug_ready(1'b1), // TODO: Detect USB cable insertion
|
||||
|
||||
|
@ -22,7 +22,7 @@ SOURCE_DIR = src
|
||||
BUILD_DIR = build
|
||||
|
||||
SRC_DIRS = $(SOURCE_DIR) $(sort $(dir $(wildcard $(SOURCE_DIR)/*/.)))
|
||||
INC_DIRS = $(addprefix -I, . $(SRC_DIRS))
|
||||
INC_DIRS = $(addprefix -I, . $(SRC_DIRS)) -I./libsc64/inc
|
||||
SRC_FILES = $(wildcard $(patsubst %, %/*.c, . $(SRC_DIRS)))
|
||||
IMG_FILES = $(wildcard $(patsubst %, %/*.png, . $(SRC_DIRS)))
|
||||
OBJ_FILES = $(addprefix $(BUILD_DIR)/, $(notdir $(IMG_FILES:.png=.o) $(SRC_FILES:.c=.o)))
|
||||
@ -32,7 +32,7 @@ VPATH = $(SRC_DIRS)
|
||||
COMMONFLAGS = -march=vr4300 -mtune=vr4300
|
||||
ASFLAGS = $(COMMONFLAGS)
|
||||
CFLAGS = $(COMMONFLAGS) -std=gnu99 -Os -Wall -I$(ROOTDIR)/mips64-elf/include $(INC_DIRS)
|
||||
LINK_FLAGS = -L$(ROOTDIR)/mips64-elf/lib -ldragon -lc -lm -ldragonsys -Tn64.ld
|
||||
LINK_FLAGS = -L$(ROOTDIR)/mips64-elf/lib -ldragon -lc -lm -ldragonsys -Tn64.ld -L./libsc64/lib -lsc64_libdragon
|
||||
N64_FLAGS = -l $(ROM_SIZE) -h $(HEADER_PATH)/$(HEADER_NAME) -o $(BUILD_DIR)/$(PROG_NAME).z64
|
||||
N64_FLAGS_PADDED = -l 1028k -h $(HEADER_PATH)/$(HEADER_NAME) -o $(BUILD_DIR)/$(PROG_NAME)_padded.z64
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
LIBDRAGON_DOCKER_VERSION=latest
|
||||
build_in_docker() {
|
||||
docker run -t \
|
||||
--mount type=bind,src=`realpath $(pwd)`,target="/src" \
|
||||
--mount type=bind,src=`realpath "$(pwd)/../libsc64"`,target="/src/libsc64" \
|
||||
$1 /bin/bash -c "cd /src && make clean && make -f $2 all"
|
||||
}
|
||||
|
||||
docker \
|
||||
run \
|
||||
-t \
|
||||
--mount type=bind,src=`realpath "$(dirname $0)"`,target="/libdragon" \
|
||||
anacierdem/libdragon:$LIBDRAGON_DOCKER_VERSION \
|
||||
/bin/bash -c "make clean && make all"
|
||||
build_in_docker "anacierdem/libdragon:latest" "Makefile"
|
||||
|
2
sw/libsc64/.gitignore
vendored
Normal file
2
sw/libsc64/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/lib
|
||||
/output
|
37
sw/libsc64/Makefile.common
Normal file
37
sw/libsc64/Makefile.common
Normal file
@ -0,0 +1,37 @@
|
||||
SRC_DIRS = src
|
||||
INC_DIRS = inc
|
||||
OUTPUT_DIR = lib
|
||||
BUILD_DIR = output/$(LIB_BUILD_DIR)
|
||||
|
||||
SRC_FILES = boot.c control.c gpio.c helpers.c init.c io_dma.c save.c sd.c usb.c
|
||||
|
||||
CFLAGS += -ffunction-sections -fdata-sections -Os -Wall -MMD -MP $(patsubst %, -I%, $(INC_DIRS))
|
||||
|
||||
OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(SRC_FILES:.c=.o)))
|
||||
DEPS = $(OBJS:.o=.d)
|
||||
|
||||
VPATH = $(SRC_DIRS)
|
||||
|
||||
all: create_build_dirs $(OUTPUT_DIR)/$(LIB_NAME).a
|
||||
|
||||
create_build_dirs: $(OUTPUT_DIR) $(BUILD_DIR)
|
||||
|
||||
$(OUTPUT_DIR):
|
||||
mkdir -p ./$(OUTPUT_DIR)
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p ./$(BUILD_DIR)
|
||||
|
||||
$(BUILD_DIR)/%.o: %.c
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(OUTPUT_DIR)/$(LIB_NAME).a: $(OBJS)
|
||||
$(AR) -rcs -o $@ $(OBJS)
|
||||
|
||||
clean:
|
||||
rm -rf ./$(BUILD_DIR) 2> /dev/null
|
||||
rm -rf ./$(OUTPUT_DIR) 2> /dev/null
|
||||
|
||||
.PHONY: all clean create_build_dirs
|
||||
|
||||
-include $(DEPS)
|
11
sw/libsc64/Makefile.libdragon
Normal file
11
sw/libsc64/Makefile.libdragon
Normal file
@ -0,0 +1,11 @@
|
||||
TOOLCHAIN = $(N64_INST)/bin/mips64-elf-
|
||||
CC = $(TOOLCHAIN)gcc
|
||||
AR = $(TOOLCHAIN)ar
|
||||
|
||||
LIB_NAME = libsc64_libdragon
|
||||
|
||||
LIB_BUILD_DIR = libdragon
|
||||
|
||||
CFLAGS += -march=vr4300 -mtune=vr4300 -DLIBDRAGON
|
||||
|
||||
include Makefile.common
|
9
sw/libsc64/Makefile.libultra
Normal file
9
sw/libsc64/Makefile.libultra
Normal file
@ -0,0 +1,9 @@
|
||||
include $(ROOT)/usr/include/make/PRdefs
|
||||
|
||||
LIB_NAME = libsc64_libultra
|
||||
|
||||
LIB_BUILD_DIR = libultra
|
||||
|
||||
CFLAGS += -I$(ROOT)/usr/include/nustd -DLIBULTRA
|
||||
|
||||
include Makefile.common
|
11
sw/libsc64/build.sh
Normal file
11
sw/libsc64/build.sh
Normal file
@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
build_in_docker() {
|
||||
docker run -t \
|
||||
--mount type=bind,src=`realpath $(pwd)`,target="/src" \
|
||||
$1 /bin/bash -c "cd /src && make -f $2 all"
|
||||
}
|
||||
|
||||
build_in_docker "anacierdem/libdragon:latest" "Makefile.libdragon"
|
||||
|
||||
build_in_docker "polprzewodnikowy/n64sdkmod:latest" "Makefile.libultra"
|
31
sw/libsc64/inc/boot.h
Normal file
31
sw/libsc64/inc/boot.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef SC64_BOOT_H__
|
||||
#define SC64_BOOT_H__
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
typedef union sc64_boot_config_s {
|
||||
uint32_t _packed_value;
|
||||
struct {
|
||||
uint16_t _padding: 16;
|
||||
bool skip_menu: 1;
|
||||
bool cic_seed_override: 1;
|
||||
bool tv_type_override: 1;
|
||||
bool ddipl_override: 1;
|
||||
bool rom_loaded: 1;
|
||||
uint8_t tv_type: 2;
|
||||
uint8_t os_version: 1;
|
||||
uint8_t cic_seed: 8;
|
||||
};
|
||||
} sc64_boot_config_t;
|
||||
|
||||
|
||||
void sc64_boot_config_set(sc64_boot_config_t *boot_config);
|
||||
void sc64_boot_config_get(sc64_boot_config_t *boot_config);
|
||||
|
||||
void sc64_boot_skip_bootloader(bool is_enabled);
|
||||
|
||||
|
||||
#endif
|
20
sw/libsc64/inc/control.h
Normal file
20
sw/libsc64/inc/control.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef SC64_CONTROL_H__
|
||||
#define SC64_CONTROL_H__
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void sc64_control_sdram_writable(bool is_enabled);
|
||||
void sc64_control_embedded_flash_access(bool is_enabled);
|
||||
|
||||
uint32_t sc64_control_version_get(void);
|
||||
|
||||
void sc64_control_ddipl_access(bool is_enabled);
|
||||
|
||||
void sc64_control_ddipl_address_set(uint32_t address);
|
||||
uint32_t sc64_control_ddipl_address_get(void);
|
||||
|
||||
|
||||
#endif
|
26
sw/libsc64/inc/gpio.h
Normal file
26
sw/libsc64/inc/gpio.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef SC64_GPIO_H__
|
||||
#define SC64_GPIO_H__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
typedef enum sc64_gpio_mode_e {
|
||||
MODE_INPUT,
|
||||
MODE_OUTPUT,
|
||||
MODE_OPEN_DRAIN,
|
||||
} sc64_gpio_mode_t;
|
||||
|
||||
|
||||
void sc64_gpio_init(void);
|
||||
|
||||
void sc64_gpio_mode_set(uint8_t num, sc64_gpio_mode_t mode);
|
||||
|
||||
void sc64_gpio_output_write(uint8_t value);
|
||||
void sc64_gpio_output_set(uint8_t mask);
|
||||
void sc64_gpio_output_clear(uint8_t mask);
|
||||
|
||||
uint8_t sc64_gpio_input_get(void);
|
||||
|
||||
|
||||
#endif
|
15
sw/libsc64/inc/helpers.h
Normal file
15
sw/libsc64/inc/helpers.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef SC64_HELPERS_H__
|
||||
#define SC64_HELPERS_H__
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void sc64_helpers_reg_write(volatile uint32_t *pi_address, uint32_t mask, bool mask_mode);
|
||||
|
||||
void sc64_helpers_reg_set(volatile uint32_t *pi_address, uint32_t mask);
|
||||
void sc64_helpers_reg_clear(volatile uint32_t *pi_address, uint32_t mask);
|
||||
|
||||
|
||||
#endif
|
8
sw/libsc64/inc/init.h
Normal file
8
sw/libsc64/inc/init.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef SC64_INIT_H__
|
||||
#define SC64_INIT_H__
|
||||
|
||||
|
||||
void sc64_init(void);
|
||||
|
||||
|
||||
#endif
|
18
sw/libsc64/inc/io_dma.h
Normal file
18
sw/libsc64/inc/io_dma.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef SC64_IO_DMA_H__
|
||||
#define SC64_IO_DMA_H__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
void sc64_io_dma_init(void);
|
||||
|
||||
void sc64_io_write(volatile uint32_t *pi_address, uint32_t value);
|
||||
uint32_t sc64_io_read(volatile uint32_t *pi_address);
|
||||
|
||||
void sc64_dma_write(void *ram_address, volatile uint32_t *pi_address, size_t length);
|
||||
void sc64_dma_read(void *ram_address, volatile uint32_t *pi_address, size_t length);
|
||||
|
||||
|
||||
#endif
|
15
sw/libsc64/inc/libsc64.h
Normal file
15
sw/libsc64/inc/libsc64.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef LIBSC64_H__
|
||||
#define LIBSC64_H__
|
||||
|
||||
|
||||
#include "boot.h"
|
||||
#include "control.h"
|
||||
#include "gpio.h"
|
||||
#include "io_dma.h"
|
||||
#include "init.h"
|
||||
#include "save.h"
|
||||
#include "sd.h"
|
||||
#include "usb.h"
|
||||
|
||||
|
||||
#endif
|
178
sw/libsc64/inc/registers.h
Normal file
178
sw/libsc64/inc/registers.h
Normal file
@ -0,0 +1,178 @@
|
||||
#ifndef SC64_REGISTERS_H__
|
||||
#define SC64_REGISTERS_H__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
// Bank definitions
|
||||
|
||||
#define SC64_BANK_SDRAM (1)
|
||||
#define SC64_BANK_EEPROM (3)
|
||||
|
||||
|
||||
// Cart Interface Registers
|
||||
|
||||
typedef struct sc64_cart_registers {
|
||||
volatile uint32_t SCR; // Cart status and control
|
||||
volatile uint32_t BOOT; // Boot behavior control
|
||||
volatile uint32_t VERSION; // Cart firmware version
|
||||
volatile uint32_t GPIO; // GPIO control
|
||||
volatile uint32_t USB_SCR; // USB interface status and control
|
||||
volatile uint32_t USB_DMA_ADDR; // USB address for DMA to PC
|
||||
volatile uint32_t USB_DMA_LEN; // USB transfer length for DMA to PC
|
||||
volatile uint32_t DDIPL_ADDR; // 64 Disk Drive IPL location in SDRAM
|
||||
volatile uint32_t SAVE_ADDR; // SRAM/FlashRAM save emulation location in SDRAM
|
||||
volatile uint32_t _unused[1015];
|
||||
volatile uint32_t USB_FIFO[1024]; // USB data from PC read FIFO memory
|
||||
} sc64_cart_registers_t;
|
||||
|
||||
|
||||
#define SC64_CART_BASE (0x1E000000)
|
||||
|
||||
#define SC64_CART ((volatile sc64_cart_registers_t *) SC64_CART_BASE)
|
||||
|
||||
|
||||
// SCR
|
||||
#define SC64_CART_SCR_SKIP_BOOTLOADER (1 << 10)
|
||||
#define SC64_CART_SCR_SD_ENABLE (1 << 9)
|
||||
#define SC64_CART_SCR_FLASHRAM_ENABLE (1 << 8)
|
||||
#define SC64_CART_SCR_SRAM_768K_MODE (1 << 7)
|
||||
#define SC64_CART_SCR_SRAM_ENABLE (1 << 6)
|
||||
#define SC64_CART_SCR_EEPROM_PI_ENABLE (1 << 5)
|
||||
#define SC64_CART_SCR_EEPROM_16K_MODE (1 << 4)
|
||||
#define SC64_CART_SCR_EEPROM_ENABLE (1 << 3)
|
||||
#define SC64_CART_SCR_DDIPL_ENABLE (1 << 2)
|
||||
#define SC64_CART_SCR_SDRAM_WRITABLE (1 << 1)
|
||||
#define SC64_CART_SCR_ROM_SWITCH (1 << 0)
|
||||
|
||||
|
||||
// GPIO
|
||||
#define SC64_CART_GPIO_OFFSET_OUTPUT (0)
|
||||
#define SC64_CART_GPIO_OFFSET_INPUT (8)
|
||||
#define SC64_CART_GPIO_OFFSET_DIR (16)
|
||||
#define SC64_CART_GPIO_OFFSET_OPEN_DRAIN (24)
|
||||
|
||||
|
||||
// USB_SCR
|
||||
#define SC64_CART_USB_SCR_FIFO_ITEMS(s) (((s) >> 3) & 0x7FF)
|
||||
#define SC64_CART_USB_SCR_READY (1 << 1)
|
||||
#define SC64_CART_USB_SCR_DMA_BUSY (1 << 0)
|
||||
|
||||
#define SC64_CART_USB_SCR_FIFO_FLUSH (1 << 2)
|
||||
#define SC64_CART_USB_SCR_DMA_START (1 << 0)
|
||||
|
||||
|
||||
// USB_DMA_ADDR
|
||||
#define SC64_CART_USB_DMA_ADDR(a) ((SC64_BANK_SDRAM << 28) | ((a) & 0x3FFFFFC))
|
||||
|
||||
|
||||
// USB_DMA_LEN
|
||||
#define SC64_CART_USB_DMA_LEN(l) (((l) - 1) & 0xFFFFF)
|
||||
|
||||
|
||||
// SD Card Interface Registers
|
||||
|
||||
typedef struct sc64_sd_registers_s {
|
||||
volatile uint32_t SCR; // Clock control and bus width selection
|
||||
volatile uint32_t ARG; // SD command argument
|
||||
volatile uint32_t CMD; // SD command index and flags
|
||||
volatile uint32_t RSP; // SD command response
|
||||
volatile uint32_t DAT; // SD data path control
|
||||
volatile uint32_t DMA_SCR; // DMA status and configuration
|
||||
volatile uint32_t DMA_ADDR; // DMA current address
|
||||
volatile uint32_t DMA_LEN; // DMA remaining length
|
||||
volatile uint32_t _unused[120];
|
||||
volatile uint32_t FIFO[128]; // SD data path FIFO buffer
|
||||
} sc64_sd_registers_t;
|
||||
|
||||
|
||||
#define SC64_SD_BASE (0x1E010000)
|
||||
|
||||
#define SC64_SD ((volatile sc64_sd_registers_t *) SC64_SD_BASE)
|
||||
|
||||
|
||||
// SCR
|
||||
#define SC64_SD_SCR_DAT_WIDTH (1 << 2)
|
||||
#define SC64_SD_SCR_CLK_MASK (0x3 << 0)
|
||||
#define SC64_SD_SCR_CLK_STOP (0 << 0)
|
||||
#define SC64_SD_SCR_CLK_400_KHZ (1 << 0)
|
||||
#define SC64_SD_SCR_CLK_25_MHZ (2 << 0)
|
||||
#define SC64_SD_SCR_CLK_50_MHZ (3 << 0)
|
||||
|
||||
|
||||
// CMD
|
||||
#define SC64_SD_CMD_RESPONSE_CRC_ERROR (1 << 8)
|
||||
#define SC64_SD_CMD_TIMEOUT (1 << 7)
|
||||
#define SC64_SD_CMD_BUSY (1 << 6)
|
||||
#define SC64_SD_CMD_INDEX_GET(cmd) ((cmd) & 0x3F)
|
||||
|
||||
#define SC64_SD_CMD_SKIP_RESPONSE (1 << 8)
|
||||
#define SC64_SD_CMD_LONG_RESPONSE (1 << 7)
|
||||
#define SC64_SD_CMD_START (1 << 6)
|
||||
#define SC64_SD_CMD_INDEX(i) ((i) & 0x3F)
|
||||
|
||||
|
||||
// DAT
|
||||
#define SC64_SD_DAT_WRITE_OK (1 << 28)
|
||||
#define SC64_SD_DAT_WRITE_ERROR (1 << 27)
|
||||
#define SC64_SD_DAT_WRITE_BUSY (1 << 26)
|
||||
#define SC64_SD_DAT_TX_FIFO_ITEMS_GET(dat) (((dat) >> 17) & 0x1FF)
|
||||
#define SC64_SD_DAT_TX_FIFO_BYTES_GET(dat) (SC64_SD_DAT_TX_FIFO_ITEMS_GET(dat) * 4)
|
||||
#define SC64_SD_DAT_TX_FIFO_FULL (1 << 16)
|
||||
#define SC64_SD_DAT_TX_FIFO_EMPTY (1 << 15)
|
||||
#define SC64_SD_DAT_TX_FIFO_UNDERRUN (1 << 14)
|
||||
#define SC64_SD_DAT_RX_FIFO_ITEMS_GET(dat) (((dat) >> 5) & 0x1FF)
|
||||
#define SC64_SD_DAT_RX_FIFO_BYTES_GET(dat) (SC64_SD_DAT_RX_FIFO_ITEMS_GET(dat) * 4)
|
||||
#define SC64_SD_DAT_RX_FIFO_FULL (1 << 4)
|
||||
#define SC64_SD_DAT_RX_FIFO_EMPTY (1 << 3)
|
||||
#define SC64_SD_DAT_RX_FIFO_OVERRUN (1 << 2)
|
||||
#define SC64_SD_DAT_CRC_ERROR (1 << 1)
|
||||
#define SC64_SD_DAT_BUSY (1 << 0)
|
||||
|
||||
#define SC64_SD_DAT_TX_FIFO_FLUSH (1 << 19)
|
||||
#define SC64_SD_DAT_RX_FIFO_FLUSH (1 << 18)
|
||||
#define SC64_SD_DAT_NUM_BLOCKS(nb) ((((nb) - 1) & 0xFF) << 10)
|
||||
#define SC64_SD_DAT_BLOCK_SIZE(bs) (((((bs) / 4) - 1) & 0x7F) << 3)
|
||||
#define SC64_SD_DAT_DIRECTION (1 << 2)
|
||||
#define SC64_SD_DAT_STOP (1 << 1)
|
||||
#define SC64_SD_DAT_START (1 << 0)
|
||||
|
||||
#define SC64_SD_DAT_FIFO_SIZE_BYTES (1024)
|
||||
#define SC64_SD_DAT_NUM_BLOCKS_MAX (256)
|
||||
#define SC64_SD_DAT_BLOCK_SIZE_MAX (512)
|
||||
|
||||
|
||||
// DMA_SCR
|
||||
#define SC64_SD_DMA_SCR_BUSY (1 << 0)
|
||||
|
||||
#define SC64_SD_DMA_SCR_DIRECTION (1 << 2)
|
||||
#define SC64_SD_DMA_SCR_STOP (1 << 1)
|
||||
#define SC64_SD_DMA_SCR_START (1 << 0)
|
||||
|
||||
|
||||
// DMA_ADDR
|
||||
#define SC64_SD_DMA_ADDR_GET(addr) ((addr) & 0x3FFFFFC)
|
||||
#define SC64_SD_DMA_BANK_GET(addr) (((addr) >> 28) & 0xF)
|
||||
|
||||
#define SC64_SD_DMA_BANK_ADDR(b, a) ((((b) & 0xF) << 28) | ((a) & 0x3FFFFFC))
|
||||
|
||||
|
||||
// DMA_LEN
|
||||
#define SC64_SD_DMA_LEN_GET(len) (((len) & 0x7FFF) * 4)
|
||||
|
||||
#define SC64_SD_DMA_LEN(l) ((((l) / 4) - 1) & 0x7FFF)
|
||||
|
||||
#define SC64_SD_DMA_LEN_MAX (0x20000)
|
||||
|
||||
|
||||
// EEPROM Block RAM
|
||||
|
||||
#define SC64_EEPROM_BASE (0x1E030000)
|
||||
|
||||
#define SC64_EEPROM ((volatile uint8_t *) SC64_EEPROM_BASE)
|
||||
|
||||
#define SC64_EEPROM_SIZE ((16 * 1024) / 8)
|
||||
|
||||
|
||||
#endif
|
31
sw/libsc64/inc/save.h
Normal file
31
sw/libsc64/inc/save.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef SC64_SAVE_H__
|
||||
#define SC64_SAVE_H__
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
typedef enum sc64_save_type_e {
|
||||
SC64_SAVE_DISABLED,
|
||||
SC64_SAVE_EEPROM_4K,
|
||||
SC64_SAVE_EEPROM_16K,
|
||||
SC64_SAVE_SRAM_256K,
|
||||
SC64_SAVE_SRAM_768K,
|
||||
SC64_SAVE_FLASHRAM_1M,
|
||||
} sc64_save_type_t;
|
||||
|
||||
|
||||
void sc64_save_type_set(sc64_save_type_t save_type);
|
||||
sc64_save_type_t sc64_save_type_get(void);
|
||||
|
||||
void sc64_save_address_set(uint32_t address);
|
||||
uint32_t sc64_save_address_get(void);
|
||||
|
||||
void sc64_save_eeprom_pi_access(bool is_enabled);
|
||||
|
||||
void sc64_save_write(void *ram_address);
|
||||
void sc64_save_read(void *ram_address);
|
||||
|
||||
|
||||
#endif
|
34
sw/libsc64/inc/sd.h
Normal file
34
sw/libsc64/inc/sd.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef SC64_SD_H__
|
||||
#define SC64_SD_H__
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void sc64_sd_access(bool is_enabled);
|
||||
|
||||
|
||||
// typedef enum sc64_sd_err_e {
|
||||
// E_OK,
|
||||
// E_TIMEOUT,
|
||||
// E_CRC_ERROR,
|
||||
// E_BAD_INDEX,
|
||||
// E_PAR_ERROR,
|
||||
// E_FIFO_ERROR,
|
||||
// E_WRITE_ERROR,
|
||||
// E_NO_INIT,
|
||||
// } sc64_sd_err_t;
|
||||
|
||||
|
||||
// bool sc64_sd_init(void);
|
||||
// void sc64_sd_deinit(void);
|
||||
// bool sc64_sd_status_get(void);
|
||||
// sc64_sd_err_t sc64_sd_sectors_read(uint32_t starting_sector, size_t count, uint8_t *buffer);
|
||||
// sc64_sd_err_t sc64_sd_sectors_write(uint32_t starting_sector, size_t count, uint8_t *buffer);
|
||||
// sc64_sd_err_t sc64_sd_sectors_read_dma(uint32_t starting_sector, size_t count, uint8_t bank, uint32_t address);
|
||||
// // sc64_sd_err_t sc64_sd_sectors_write_dma(uint32_t starting_sector, size_t count, uint8_t bank, uint32_t address);
|
||||
// sc64_sd_err_t sc64_sd_dat_busy_wait(void);
|
||||
|
||||
|
||||
#endif
|
8
sw/libsc64/inc/usb.h
Normal file
8
sw/libsc64/inc/usb.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef SC64_USB_H__
|
||||
#define SC64_USB_H__
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
17
sw/libsc64/src/boot.c
Normal file
17
sw/libsc64/src/boot.c
Normal file
@ -0,0 +1,17 @@
|
||||
#include "boot.h"
|
||||
#include "helpers.h"
|
||||
#include "io_dma.h"
|
||||
#include "registers.h"
|
||||
|
||||
|
||||
void sc64_boot_skip_bootloader(bool is_enabled) {
|
||||
sc64_helpers_reg_write(&SC64_CART->SCR, SC64_CART_SCR_SKIP_BOOTLOADER, is_enabled);
|
||||
}
|
||||
|
||||
void sc64_boot_config_set(sc64_boot_config_t *boot_config) {
|
||||
sc64_io_write(&SC64_CART->BOOT, boot_config->_packed_value);
|
||||
}
|
||||
|
||||
void sc64_boot_config_get(sc64_boot_config_t *boot_config) {
|
||||
boot_config->_packed_value = sc64_io_read(&SC64_CART->BOOT);
|
||||
}
|
29
sw/libsc64/src/control.c
Normal file
29
sw/libsc64/src/control.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include "control.h"
|
||||
#include "helpers.h"
|
||||
#include "io_dma.h"
|
||||
#include "registers.h"
|
||||
|
||||
|
||||
void sc64_control_sdram_writable(bool is_enabled) {
|
||||
sc64_helpers_reg_write(&SC64_CART->SCR, SC64_CART_SCR_SDRAM_WRITABLE, is_enabled);
|
||||
}
|
||||
|
||||
void sc64_control_embedded_flash_access(bool is_enabled) {
|
||||
sc64_helpers_reg_write(&SC64_CART->SCR, SC64_CART_SCR_ROM_SWITCH, !is_enabled);
|
||||
}
|
||||
|
||||
uint32_t sc64_control_version_get(void) {
|
||||
return sc64_io_read(&SC64_CART->VERSION);
|
||||
}
|
||||
|
||||
void sc64_control_ddipl_access(bool is_enabled) {
|
||||
sc64_helpers_reg_write(&SC64_CART->SCR, SC64_CART_SCR_DDIPL_ENABLE, is_enabled);
|
||||
}
|
||||
|
||||
void sc64_control_ddipl_address_set(uint32_t address) {
|
||||
sc64_io_write(&SC64_CART->DDIPL_ADDR, address);
|
||||
}
|
||||
|
||||
uint32_t sc64_control_ddipl_address_get(void) {
|
||||
return sc64_io_read(&SC64_CART->DDIPL_ADDR);
|
||||
}
|
63
sw/libsc64/src/gpio.c
Normal file
63
sw/libsc64/src/gpio.c
Normal file
@ -0,0 +1,63 @@
|
||||
#include "gpio.h"
|
||||
#include "io_dma.h"
|
||||
#include "registers.h"
|
||||
|
||||
|
||||
static uint32_t gpio_state;
|
||||
|
||||
|
||||
void sc64_gpio_init(void) {
|
||||
gpio_state = 0;
|
||||
|
||||
sc64_io_write(&SC64_CART->GPIO, gpio_state);
|
||||
}
|
||||
|
||||
void sc64_gpio_mode_set(uint8_t num, sc64_gpio_mode_t mode) {
|
||||
if (num >= 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_state &= ~(
|
||||
((1 << num) << SC64_CART_GPIO_OFFSET_OPEN_DRAIN) |
|
||||
((1 << num) << SC64_CART_GPIO_OFFSET_DIR)
|
||||
);
|
||||
|
||||
switch (mode) {
|
||||
case MODE_OUTPUT:
|
||||
gpio_state |= ((1 << num) << SC64_CART_GPIO_OFFSET_DIR);
|
||||
break;
|
||||
case MODE_OPEN_DRAIN:
|
||||
gpio_state |= (
|
||||
((1 << num) << SC64_CART_GPIO_OFFSET_OPEN_DRAIN) |
|
||||
((1 << num) << SC64_CART_GPIO_OFFSET_DIR)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
sc64_io_write(&SC64_CART->GPIO, gpio_state);
|
||||
}
|
||||
|
||||
void sc64_gpio_output_write(uint8_t value) {
|
||||
gpio_state &= ~(0xFF << SC64_CART_GPIO_OFFSET_OUTPUT);
|
||||
gpio_state |= (value << SC64_CART_GPIO_OFFSET_OUTPUT);
|
||||
|
||||
sc64_io_write(&SC64_CART->GPIO, gpio_state);
|
||||
}
|
||||
|
||||
void sc64_gpio_output_set(uint8_t mask) {
|
||||
gpio_state |= (mask << SC64_CART_GPIO_OFFSET_OUTPUT);
|
||||
|
||||
sc64_io_write(&SC64_CART->GPIO, gpio_state);
|
||||
}
|
||||
|
||||
void sc64_gpio_output_clear(uint8_t mask) {
|
||||
gpio_state &= ~(mask << SC64_CART_GPIO_OFFSET_OUTPUT);
|
||||
|
||||
sc64_io_write(&SC64_CART->GPIO, gpio_state);
|
||||
}
|
||||
|
||||
uint8_t sc64_gpio_input_get(void) {
|
||||
return (uint8_t) ((sc64_io_read(&SC64_CART->GPIO) >> SC64_CART_GPIO_OFFSET_INPUT) & 0xFF);
|
||||
}
|
24
sw/libsc64/src/helpers.c
Normal file
24
sw/libsc64/src/helpers.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include "helpers.h"
|
||||
#include "io_dma.h"
|
||||
#include "registers.h"
|
||||
|
||||
|
||||
void sc64_helpers_reg_write(volatile uint32_t *pi_address, uint32_t mask, bool mask_mode) {
|
||||
uint32_t reg = sc64_io_read(pi_address);
|
||||
|
||||
if (mask_mode) {
|
||||
reg |= mask;
|
||||
} else {
|
||||
reg &= ~mask;
|
||||
}
|
||||
|
||||
sc64_io_write(pi_address, reg);
|
||||
}
|
||||
|
||||
void sc64_helpers_reg_set(volatile uint32_t *pi_address, uint32_t mask) {
|
||||
sc64_helpers_reg_write(pi_address, mask, true);
|
||||
}
|
||||
|
||||
void sc64_helpers_reg_clear(volatile uint32_t *pi_address, uint32_t mask) {
|
||||
sc64_helpers_reg_write(pi_address, mask, false);
|
||||
}
|
8
sw/libsc64/src/init.c
Normal file
8
sw/libsc64/src/init.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include "gpio.h"
|
||||
#include "io_dma.h"
|
||||
|
||||
|
||||
void sc64_init(void) {
|
||||
sc64_io_dma_init();
|
||||
sc64_gpio_init();
|
||||
}
|
69
sw/libsc64/src/io_dma.c
Normal file
69
sw/libsc64/src/io_dma.c
Normal file
@ -0,0 +1,69 @@
|
||||
#include "io_dma.h"
|
||||
|
||||
|
||||
#ifndef LIBDRAGON
|
||||
#ifndef LIBULTRA
|
||||
#error "Please specify used library with -DLIBDRAGON or -DLIBULTRA"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LIBDRAGON
|
||||
#include <libdragon.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LIBULTRA
|
||||
#include <ultra64.h>
|
||||
|
||||
static OSMesg pi_message;
|
||||
static OSIoMesg pi_io_message;
|
||||
static OSMesgQueue pi_message_queue;
|
||||
#endif
|
||||
|
||||
|
||||
void sc64_io_dma_init(void) {
|
||||
#ifdef LIBULTRA
|
||||
osCreateMesgQueue(&pi_message_queue, &pi_message, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sc64_io_write(volatile uint32_t *pi_address, uint32_t value) {
|
||||
#ifdef LIBDRAGON
|
||||
io_write((uint32_t) pi_address, value);
|
||||
#elif LIBULTRA
|
||||
osPiWriteIo((u32) pi_address, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t sc64_io_read(volatile uint32_t *pi_address) {
|
||||
#ifdef LIBDRAGON
|
||||
return io_read((uint32_t) pi_address);
|
||||
#elif LIBULTRA
|
||||
u32 value;
|
||||
osPiReadIo((u32) pi_address, &value);
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
void sc64_dma_write(void *ram_address, volatile uint32_t *pi_address, size_t length) {
|
||||
#ifdef LIBDRAGON
|
||||
data_cache_hit_writeback_invalidate(ram_address, length);
|
||||
dma_write(ram_address, (uint32_t) pi_address, length);
|
||||
#elif LIBULTRA
|
||||
osWritebackDCache(ram_address, length);
|
||||
osPiStartDma(&pi_io_message, OS_MESG_PRI_NORMAL, OS_WRITE, (u32) pi_address, ram_address, length, &pi_message_queue);
|
||||
osRecvMesg(&pi_message_queue, NULL, OS_MESG_BLOCK);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sc64_dma_read(void *ram_address, volatile uint32_t *pi_address, size_t length) {
|
||||
#ifdef LIBDRAGON
|
||||
dma_read(ram_address, (uint32_t) pi_address, length);
|
||||
data_cache_hit_writeback_invalidate(ram_address, length);
|
||||
#elif LIBULTRA
|
||||
osPiStartDma(&pi_io_message, OS_MESG_PRI_NORMAL, OS_READ, (u32) pi_address, ram_address, length, &pi_message_queue);
|
||||
osRecvMesg(&pi_message_queue, NULL, OS_MESG_BLOCK);
|
||||
osInvalDCache(ram_address, length);
|
||||
#endif
|
||||
}
|
157
sw/libsc64/src/save.c
Normal file
157
sw/libsc64/src/save.c
Normal file
@ -0,0 +1,157 @@
|
||||
#include "control.h"
|
||||
#include "helpers.h"
|
||||
#include "io_dma.h"
|
||||
#include "registers.h"
|
||||
#include "save.h"
|
||||
|
||||
|
||||
static bool sc64_save_address_length_get(uint32_t *pi_address, size_t *length, bool *is_eeprom) {
|
||||
sc64_save_type_t save_type = sc64_save_type_get();
|
||||
|
||||
*is_eeprom = false;
|
||||
|
||||
switch (save_type) {
|
||||
case SC64_SAVE_EEPROM_4K:
|
||||
*pi_address = SC64_EEPROM_BASE;
|
||||
*length = 512;
|
||||
*is_eeprom = true;
|
||||
break;
|
||||
case SC64_SAVE_EEPROM_16K:
|
||||
*pi_address = SC64_EEPROM_BASE;
|
||||
*length = 2048;
|
||||
*is_eeprom = true;
|
||||
break;
|
||||
case SC64_SAVE_SRAM_256K:
|
||||
*pi_address = sc64_save_address_get();
|
||||
*length = (32 * 1024);
|
||||
break;
|
||||
case SC64_SAVE_SRAM_768K:
|
||||
*pi_address = sc64_save_address_get();
|
||||
*length = (96 * 1024);
|
||||
break;
|
||||
case SC64_SAVE_FLASHRAM_1M:
|
||||
*pi_address = sc64_save_address_get();
|
||||
*length = (128 * 1024);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void sc64_save_type_set(sc64_save_type_t save_type) {
|
||||
uint32_t scr;
|
||||
|
||||
scr = sc64_io_read(&SC64_CART->SCR);
|
||||
|
||||
scr &= ~(
|
||||
SC64_CART_SCR_FLASHRAM_ENABLE |
|
||||
SC64_CART_SCR_SRAM_768K_MODE |
|
||||
SC64_CART_SCR_SRAM_ENABLE |
|
||||
SC64_CART_SCR_EEPROM_16K_MODE |
|
||||
SC64_CART_SCR_EEPROM_ENABLE
|
||||
);
|
||||
|
||||
switch (save_type)
|
||||
{
|
||||
case SC64_SAVE_EEPROM_4K:
|
||||
scr |= SC64_CART_SCR_EEPROM_ENABLE;
|
||||
break;
|
||||
case SC64_SAVE_EEPROM_16K:
|
||||
scr |= SC64_CART_SCR_EEPROM_ENABLE | SC64_CART_SCR_EEPROM_16K_MODE;
|
||||
break;
|
||||
case SC64_SAVE_SRAM_256K:
|
||||
scr |= SC64_CART_SCR_SRAM_ENABLE;
|
||||
break;
|
||||
case SC64_SAVE_SRAM_768K:
|
||||
scr |= SC64_CART_SCR_SRAM_ENABLE | SC64_CART_SCR_SRAM_768K_MODE;
|
||||
break;
|
||||
case SC64_SAVE_FLASHRAM_1M:
|
||||
scr |= SC64_CART_SCR_FLASHRAM_ENABLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
sc64_io_write(&SC64_CART->SCR, scr);
|
||||
}
|
||||
|
||||
sc64_save_type_t sc64_save_type_get(void) {
|
||||
uint32_t scr;
|
||||
|
||||
scr = sc64_io_read(&SC64_CART->SCR);
|
||||
|
||||
if (scr & SC64_CART_SCR_FLASHRAM_ENABLE) {
|
||||
return SC64_SAVE_FLASHRAM_1M;
|
||||
} else if (scr & SC64_CART_SCR_SRAM_ENABLE) {
|
||||
return (scr & SC64_CART_SCR_SRAM_768K_MODE) ? SC64_SAVE_SRAM_768K : SC64_SAVE_SRAM_256K;
|
||||
} else if (scr & SC64_CART_SCR_EEPROM_ENABLE) {
|
||||
return (scr & SC64_CART_SCR_EEPROM_16K_MODE) ? SC64_SAVE_EEPROM_16K : SC64_SAVE_EEPROM_4K;
|
||||
}
|
||||
|
||||
return SC64_SAVE_DISABLED;
|
||||
}
|
||||
|
||||
void sc64_save_address_set(uint32_t address) {
|
||||
sc64_io_write(&SC64_CART->SAVE_ADDR, address);
|
||||
}
|
||||
|
||||
uint32_t sc64_save_address_get(void) {
|
||||
return sc64_io_read(&SC64_CART->SAVE_ADDR);
|
||||
}
|
||||
|
||||
void sc64_save_eeprom_pi_access(bool is_enabled) {
|
||||
sc64_helpers_reg_write(&SC64_CART->SCR, SC64_CART_SCR_EEPROM_PI_ENABLE, is_enabled);
|
||||
}
|
||||
|
||||
void sc64_save_write(void *ram_address) {
|
||||
uint32_t pi_address;
|
||||
size_t length;
|
||||
bool is_eeprom;
|
||||
uint32_t scr;
|
||||
bool eeprom_pi_access;
|
||||
bool sdram_writable;
|
||||
|
||||
if (sc64_save_address_length_get(&pi_address, &length, &is_eeprom)) {
|
||||
scr = sc64_io_read(&SC64_CART->SCR);
|
||||
eeprom_pi_access = scr & SC64_CART_SCR_EEPROM_PI_ENABLE;
|
||||
sdram_writable = scr & SC64_CART_SCR_SDRAM_WRITABLE;
|
||||
|
||||
if (is_eeprom && !eeprom_pi_access) {
|
||||
sc64_save_eeprom_pi_access(true);
|
||||
} else if (!sdram_writable) {
|
||||
sc64_control_sdram_writable(true);
|
||||
}
|
||||
|
||||
sc64_dma_write(ram_address, (volatile uint32_t *) pi_address, length);
|
||||
|
||||
if (is_eeprom && !eeprom_pi_access) {
|
||||
sc64_save_eeprom_pi_access(false);
|
||||
} else if (!sdram_writable) {
|
||||
sc64_control_sdram_writable(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sc64_save_read(void *ram_address) {
|
||||
uint32_t pi_address;
|
||||
size_t length;
|
||||
bool is_eeprom;
|
||||
bool eeprom_pi_access;
|
||||
|
||||
if (sc64_save_address_length_get(&pi_address, &length, &is_eeprom)) {
|
||||
eeprom_pi_access = sc64_io_read(&SC64_CART->SCR) & SC64_CART_SCR_EEPROM_PI_ENABLE;
|
||||
|
||||
if (is_eeprom && !eeprom_pi_access) {
|
||||
sc64_save_eeprom_pi_access(true);
|
||||
}
|
||||
|
||||
sc64_dma_read(ram_address, (volatile uint32_t *) pi_address, length);
|
||||
|
||||
if (is_eeprom && !eeprom_pi_access) {
|
||||
sc64_save_eeprom_pi_access(false);
|
||||
}
|
||||
}
|
||||
}
|
211
sw/libsc64/src/sd.c
Normal file
211
sw/libsc64/src/sd.c
Normal file
@ -0,0 +1,211 @@
|
||||
#include "helpers.h"
|
||||
#include "registers.h"
|
||||
#include "sd.h"
|
||||
|
||||
|
||||
void sc64_sd_access(bool is_enabled) {
|
||||
sc64_helpers_reg_write(&SC64_CART->SCR, SC64_CART_SCR_SD_ENABLE, is_enabled);
|
||||
}
|
||||
|
||||
|
||||
// #include "registers.h"
|
||||
// #include "sd.h"
|
||||
// #include "io_dma.h"
|
||||
|
||||
|
||||
// #define CMD8_ARG_SUPPLY_VOLTAGE_27_36_V (1 << 8)
|
||||
// #define CMD8_ARG_CHECK_PATTERN_AA (0xAA << 0)
|
||||
|
||||
// #define ACMD41_ARG_HCS (1 << 30)
|
||||
|
||||
// #define R3_CCS (1 << 30)
|
||||
// #define R3_BUSY (1 << 31)
|
||||
|
||||
// #define R7_SUPPLY_VOLTAGE_27_36_V (1 << 8)
|
||||
// #define R7_CHECK_PATTERN_AA (0xAA << 0)
|
||||
|
||||
// #define SD_BLOCK_SIZE (512)
|
||||
|
||||
|
||||
// typedef enum sc64_sd_cmd_flags_e {
|
||||
// NO_FLAGS = 0,
|
||||
// ACMD = (1 << 0),
|
||||
// SKIP_RESPONSE = (1 << 1),
|
||||
// LONG_RESPONSE = (1 << 2),
|
||||
// IGNORE_CRC = (1 << 3),
|
||||
// IGNORE_INDEX = (1 << 4),
|
||||
// } sc64_sd_cmd_flags_t;
|
||||
|
||||
|
||||
// static bool sd_card_initialized = false;
|
||||
// static bool sd_card_type_block = false;
|
||||
// static bool sd_card_selected = false;
|
||||
// static uint32_t sd_card_rca = 0;
|
||||
// static uint8_t sd_buffer[64] __attribute__((aligned(16)));
|
||||
|
||||
|
||||
// static void sc64_sd_clock_set(uint32_t clock) {
|
||||
// uint32_t scr = sc64_io_read(&SC64_SD->SCR);
|
||||
|
||||
// sc64_io_write(&SC64_SD->SCR, (scr & (~SC64_SD_SCR_CLK_MASK)) | (clock & SC64_SD_SCR_CLK_MASK));
|
||||
// }
|
||||
|
||||
// static void sc64_sd_dat_4bit_set(bool is_4bit) {
|
||||
// uint32_t scr = sc64_io_read(&SC64_SD->SCR);
|
||||
|
||||
// scr &= ~SC64_SD_SCR_DAT_WIDTH;
|
||||
|
||||
// if (is_4bit) {
|
||||
// scr |= SC64_SD_SCR_DAT_WIDTH;
|
||||
// }
|
||||
|
||||
// sc64_io_write(&SC64_SD->SCR, scr);
|
||||
// }
|
||||
|
||||
// static void sc64_sd_peripheral_reset(void) {
|
||||
// while (sc64_io_read(&SC64_SD->CMD) & SC64_SD_CMD_BUSY);
|
||||
// sc64_io_write(&SC64_SD->DMA_SCR, SC64_SD_DMA_SCR_STOP);
|
||||
// sc64_io_write(&SC64_SD->DAT, SC64_SD_DAT_TX_FIFO_FLUSH | SC64_SD_DAT_RX_FIFO_FLUSH | SC64_SD_DAT_STOP);
|
||||
// sc64_io_write(&SC64_SD->SCR, 0);
|
||||
// }
|
||||
|
||||
// static void sc64_sd_peripheral_init(void) {
|
||||
// sc64_control_sd_enable();
|
||||
// sc64_sd_peripheral_reset();
|
||||
// }
|
||||
|
||||
// static void sc64_sd_peripheral_deinit(void) {
|
||||
// if (sc64_control_sd_is_enabled()) {
|
||||
// sc64_sd_peripheral_reset();
|
||||
// }
|
||||
// sc64_control_sd_disable();
|
||||
// }
|
||||
|
||||
// static bool sc64_sd_cmd_send(uint8_t index, uint32_t arg, sc64_sd_cmd_flags_t flags, uint32_t *response) {
|
||||
// uint32_t reg;
|
||||
|
||||
// if (flags & ACMD) {
|
||||
// if (!sc64_sd_cmd_send(55, sd_card_rca, NO_FLAGS, response)) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// sc64_io_write(&SC64_SD->ARG, arg);
|
||||
|
||||
// reg = SC64_SD_CMD_START | SC64_SD_CMD_INDEX(index);
|
||||
// if (flags & SKIP_RESPONSE) {
|
||||
// reg |= SC64_SD_CMD_SKIP_RESPONSE;
|
||||
// }
|
||||
// if (flags & LONG_RESPONSE) {
|
||||
// reg |= SC64_SD_CMD_LONG_RESPONSE;
|
||||
// }
|
||||
|
||||
// sc64_io_write(&SC64_SD->CMD, reg);
|
||||
|
||||
// do {
|
||||
// reg = sc64_io_read(&SC64_SD->CMD);
|
||||
// } while (reg & SC64_SD_CMD_BUSY);
|
||||
|
||||
// *response = sc64_io_read(&SC64_SD->RSP);
|
||||
|
||||
// return (
|
||||
// (reg & SC64_SD_CMD_TIMEOUT) |
|
||||
// ((!(flags & SKIP_RESPONSE)) && (
|
||||
// ((!(flags & IGNORE_CRC)) && (reg & SC64_SD_CMD_RESPONSE_CRC_ERROR)) |
|
||||
// ((!(flags & IGNORE_INDEX)) && (SC64_SD_CMD_INDEX_GET(reg) != index))
|
||||
// ))
|
||||
// );
|
||||
// }
|
||||
|
||||
|
||||
// bool sc64_sd_init(void) {
|
||||
// bool success;
|
||||
// uint32_t response;
|
||||
// uint32_t argument;
|
||||
|
||||
// if (sd_card_initialized) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// sc64_sd_peripheral_init();
|
||||
|
||||
// do {
|
||||
// sc64_sd_cmd_send(0, 0, SKIP_RESPONSE, &response);
|
||||
|
||||
// argument = CMD8_ARG_SUPPLY_VOLTAGE_27_36_V | CMD8_ARG_CHECK_PATTERN_AA;
|
||||
// success = sc64_sd_cmd_send(8, argument, NO_FLAGS, &response);
|
||||
// if (success && (response != (R7_SUPPLY_VOLTAGE_27_36_V | R7_CHECK_PATTERN_AA))) {
|
||||
// break;
|
||||
// }
|
||||
|
||||
// argument = (success ? ACMD41_ARG_HCS : 0) | 0x00FF8000;
|
||||
// for (int i = 0; i < 4000; i++) {
|
||||
// success = sc64_sd_cmd_send(41, argument, ACMD | IGNORE_CRC | IGNORE_INDEX, &response);
|
||||
// if (!success || (response & R3_BUSY)) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (!success || ((response & 0x00FF8000) == 0)) {
|
||||
// break;
|
||||
// }
|
||||
// sd_card_type_block = (response & R3_CCS) ? true : false;
|
||||
|
||||
// success = sc64_sd_cmd_send(2, 0, LONG_RESPONSE | IGNORE_INDEX, &response);
|
||||
// if (!success) {
|
||||
// break;
|
||||
// }
|
||||
|
||||
// success = sc64_sd_cmd_send(3, 0, NO_FLAGS, &response);
|
||||
// if (!success) {
|
||||
// break;
|
||||
// }
|
||||
// sd_card_rca = response & 0xFFFF0000;
|
||||
|
||||
// success = sc64_sd_cmd_send(7, sd_card_rca, NO_FLAGS, &response);
|
||||
// if (!success) {
|
||||
// break;
|
||||
// }
|
||||
// sd_card_selected = true;
|
||||
|
||||
// success = sc64_sd_cmd_send(6, 2, ACMD, &response);
|
||||
// if (!success) {
|
||||
// break;
|
||||
// }
|
||||
|
||||
// sc64_sd_clock_set(SC64_SD_SCR_CLK_25_MHZ);
|
||||
// sc64_sd_dat_4bit_set(true);
|
||||
|
||||
// sc64_sd_dat_prepare(1, 64, DAT_DIR_RX);
|
||||
// success = sc64_sd_cmd_send(6, 0x00000001, NO_FLAGS, &response);
|
||||
// if (!success) {
|
||||
// sc64_sd_dat_abort();
|
||||
// break;
|
||||
// }
|
||||
// success = sc64_sd_dat_read(64, sd_buffer);
|
||||
// if (!success) {
|
||||
// break;
|
||||
// }
|
||||
// if (sd_buffer[13] & 0x02) {
|
||||
// sc64_sd_dat_prepare(1, 64, DAT_DIR_RX);
|
||||
// success = sc64_sd_cmd_send(6, 0x80000001, NO_FLAGS, &response);
|
||||
// if (!success) {
|
||||
// sc64_sd_dat_abort();
|
||||
// break;
|
||||
// }
|
||||
// success = sc64_sd_dat_read(64, sd_buffer);
|
||||
// if (!success) {
|
||||
// break;
|
||||
// }
|
||||
|
||||
// sc64_sd_clock_set(SC64_SD_SCR_CLK_50_MHZ);
|
||||
// }
|
||||
|
||||
// sd_card_initialized = true;
|
||||
|
||||
// return true;
|
||||
// } while(0);
|
||||
|
||||
// sc64_sd_deinit();
|
||||
|
||||
// return false;
|
||||
// }
|
1
sw/libsc64/src/usb.c
Normal file
1
sw/libsc64/src/usb.c
Normal file
@ -0,0 +1 @@
|
||||
#include "usb.h"
|
Loading…
Reference in New Issue
Block a user