gint: basic support for fx-CP 400 programs with HollyHock 2 loading

Features will come in slowly while I restructure for gint 3. With this
third big target for gint, the legacy aspects of gint 2's structure and
API are getting felt, so a major revision will be in order.

See the TODO file at this commit for info on what works and not.
This commit is contained in:
Lephe 2024-04-16 15:53:10 +02:00
parent 5c3dc3220a
commit 789ba7caa5
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
26 changed files with 657 additions and 38 deletions

View file

@ -124,6 +124,7 @@ set(SOURCES
src/kernel/kernel.c src/kernel/kernel.c
src/kernel/osmenu.c src/kernel/osmenu.c
src/kernel/start.c src/kernel/start.c
src/kernel/start.S
src/kernel/syscalls.S src/kernel/syscalls.S
src/kernel/tlbh.S src/kernel/tlbh.S
src/kernel/world.c src/kernel/world.c
@ -144,6 +145,8 @@ set(SOURCES
src/kmalloc/kmalloc.c src/kmalloc/kmalloc.c
# MMU driver # MMU driver
src/mmu/mmu.c src/mmu/mmu.c
# R61523 display driver
src/r61523/r61523.c
# R61524 display driver # R61524 display driver
src/r61524/r61524.c src/r61524/r61524.c
# Format-agnostic rendering # Format-agnostic rendering
@ -250,6 +253,7 @@ set(SOURCES
set(ASSETS_FX src/font5x7.png src/gdb/icons-i1msb.png) set(ASSETS_FX src/font5x7.png src/gdb/icons-i1msb.png)
set(ASSETS_CG src/font8x9.png src/gdb/icons-rgb565.png) set(ASSETS_CG src/font8x9.png src/gdb/icons-rgb565.png)
set(ASSETS_CP ${ASSETS_CG})
fxconv_declare_assets(${ASSETS_FX} ${ASSETS_CG}) fxconv_declare_assets(${ASSETS_FX} ${ASSETS_CG})
include_directories( include_directories(
@ -283,6 +287,14 @@ if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_G3A)
add_library(${NAME} STATIC ${SOURCES} ${ASSETS_FX} ${LINKER_SCRIPTS}) add_library(${NAME} STATIC ${SOURCES} ${ASSETS_FX} ${LINKER_SCRIPTS})
endif() endif()
if("${FXSDK_PLATFORM_LONG}" STREQUAL fxCP)
add_compile_definitions(FXCP)
set(NAME "gint-cp")
set(LINKER_SCRIPTS
"${CMAKE_CURRENT_BINARY_DIR}/fxcp_hh2.ld")
add_library(${NAME} STATIC ${SOURCES} ${ASSETS_CP} ${LINKER_SCRIPTS})
endif()
set_target_properties("${NAME}" PROPERTIES OUTPUT_NAME "${NAME}") set_target_properties("${NAME}" PROPERTIES OUTPUT_NAME "${NAME}")
# Generate linker scripts # Generate linker scripts
@ -296,6 +308,7 @@ endmacro()
generate_linker_script("fx9860g.ld" "fx9860g.ld.c" "") generate_linker_script("fx9860g.ld" "fx9860g.ld.c" "")
generate_linker_script("fxcg50.ld" "fxcg50.ld.c" "") generate_linker_script("fxcg50.ld" "fxcg50.ld.c" "")
generate_linker_script("fxcg50_fastload.ld" "fxcg50.ld.c" "-DFXCG50_FASTLOAD") generate_linker_script("fxcg50_fastload.ld" "fxcg50.ld.c" "-DFXCG50_FASTLOAD")
generate_linker_script("fxcp_hh2.ld" "fxcp_hh2.ld.c" "")
# Library file # Library file
install(TARGETS "${NAME}" DESTINATION "${FXSDK_LIB}") install(TARGETS "${NAME}" DESTINATION "${FXSDK_LIB}")

26
TODO
View file

@ -25,9 +25,6 @@ Future directions:
* Make fx9860g projects work out of the box on fxcg50 * Make fx9860g projects work out of the box on fxcg50
* Base for Yatis' threads library * Base for Yatis' threads library
TODO:
* SPLIT CONFIG HEADER IN VARIANTS SO THEY DON'T CLASH WHEN INSTALLED
Bits that need to abstract out into APIs: Bits that need to abstract out into APIs:
- display: Toggle backlight (or set level) - display: Toggle backlight (or set level)
-> Have a backlight property with min/max values -> Have a backlight property with min/max values
@ -61,6 +58,25 @@ enum {
/* Indexed 2-bit: white, light gray, dark gray, black. Represented as a /* Indexed 2-bit: white, light gray, dark gray, black. Represented as a
pair of I1MSB buffers, the first being bit #0, the second bit #1. */ pair of I1MSB buffers, the first being bit #0, the second bit #1. */
IMAGE_FORMAT_2I1MSB, IMAGE_FORMAT_2I1MSB,
/* 16-bit RGB565. Row-major, left-to-right. */
IMAGE_FORMAT_RGB565,
}; };
fx-CP port progress.
DONE:
- kernel can start add-ins, take over interrupts (but no interrupt sources yet)
- panic handler works (no interactive choices, only RESET)
- no OS menu (likely never) and poweroff (maybe later)
- memory: 64 kB total + OS heap (no gint arena, no MMU)
- r61523: prototype display driver
- can use the rendering pipeline with no DMA acceleration
IN-PROGRESS:
- unification of the image/video interface
TODO:
- hardware info: rom and fs type
- quit handler
- DMA acceleration for dclear and dupdate
- keyboard and touch screen input
- drivers: cpg, dma, intc, rtc, tmu
- find more memory, 64 kB is not enough
- benchmark memory and display performance
- improve API and performance of display driver
- way off: filesystem, remote debugging, usb

View file

@ -11,6 +11,10 @@ elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_G3A)
set(PC fxg3a) set(PC fxg3a)
set(INTF_DEFN FX9860G_G3A) set(INTF_DEFN FX9860G_G3A)
set(INTF_LINK "-T;fxcg50.ld") set(INTF_LINK "-T;fxcg50.ld")
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCP)
set(PC cp)
set(INTF_DEFN FXCP)
set(INTF_LINK "-T;fxcp_hh2.ld")
else() else()
message(FATAL_ERROR "gint: unknown fxSDK platform '${FXSDK_PLATFORM}'") message(FATAL_ERROR "gint: unknown fxSDK platform '${FXSDK_PLATFORM}'")
endif() endif()

189
fxcp_hh2.ld.c Normal file
View file

@ -0,0 +1,189 @@
/*
Linker script for fxCP add-ins linking with HollyHock2.
*/
OUTPUT_ARCH(sh4)
OUTPUT_FORMAT(elf32-sh)
ENTRY(_start_header)
MEMORY
{
/* Everything mixed together loaded as one */
ram (rwx): o = 0x8cff0000, l = 61184 /* 64k - 0x1100 */
/* Space for the vbr */
vbr (rwx): o = 0x8cffef00, l = 0x1100
/* On-chip IL memory */
ilram (rwx): o = 0xe5200000, l = 4k
/* On-chip X and Y memory */
xyram (rwx): o = 0xe500e000, l = 16k
}
SECTIONS
{
/*
** ROM sections
*/
/* First address to be mapped to ROM */
_brom = ORIGIN(ram);
/* Size of ROM mappings */
_srom = SIZEOF(.text) + SIZEOF(.rodata)
+ SIZEOF(.gint.drivers) + SIZEOF(.gint.blocks);
/* Machine code going to ROM:
- Entry function (.text.entry)
- Compiler-provided constructors (.ctors) and destructors (.dtors)
- All text from .text and .text.* (including user code) */
.text : {
*(.text.header)
*(.hh2info)
*(.text.entry)
_bctors = . ;
*(.ctors .ctors.*)
_ectors = . ;
_bdtors = . ;
*(.dtors .dtors.*)
_edtors = . ;
_gint_exch_start = . ;
*(.gint.exch)
_gint_exch_size = ABSOLUTE(. - _gint_exch_start);
_gint_tlbh_start = . ;
*(.gint.tlbh)
_gint_tlbh_size = ABSOLUTE(. - _gint_tlbh_start);
*(.text .text.*)
} > ram
/* gint's interrupt handler blocks (.gint.blocks)
Although gint's blocks end up in VBR space, they are relocated at
startup by the library/drivers, so we store them here for now */
.gint.blocks : {
KEEP(*(.gint.blocks));
} > ram
/* Exposed driver interfaces (.gint.drivers)
The driver information is required to start and configure the
driver, even if the symbols are not referenced */
.gint.drivers : {
_gint_drivers = . ;
KEEP(*(SORT_BY_NAME(.gint.drivers.*)));
_gint_drivers_end = . ;
} > ram
/* Read-only data going to ROM:
- Resources or assets from fxconv or similar converters
- Data marked read-only by the compiler (.rodata and .rodata.*) */
.rodata : SUBALIGN(4) {
/* Put these first, they need to be 4-aligned */
*(.rodata.4)
*(.rodata .rodata.*)
} > ram
/*
** RAM sections
*/
. = ALIGN(16); /* No effect? */
/* Read-write data sections going to RAM (.data and .data.*) */
.data ALIGN(4) : ALIGN(4) {
_ldata = LOADADDR(.data);
_rdata = . ;
*(.data .data.*)
/* Code that must remain mapped; no MMU on HH2, so fine */
*(.gint.mapped)
/* References to mapped code - no relocation needed */
*(.gint.mappedrel)
. = ALIGN(16);
} > ram
/* Read-write data sub-aligned to 4 bytes (mainly from fxconv) */
.data.4 : SUBALIGN(4) {
*(.data.4)
. = ALIGN(16);
} > ram
_sdata = SIZEOF(.data) + SIZEOF(.data.4);
/* On-chip memory sections: IL, X and Y memory */
. = ORIGIN(ilram);
.ilram ALIGN(4) : ALIGN(4) {
_lilram = LOADADDR(.ilram);
_rilram = . ;
*(.ilram)
. = ALIGN(16);
} > ilram AT> ram
. = ORIGIN(xyram);
.xyram ALIGN(4) : ALIGN(4) {
_lxyram = LOADADDR(.xyram);
_rxyram = . ;
*(.xram .yram .xyram)
. = ALIGN(16);
} > xyram AT> ram
_silram = SIZEOF(.ilram);
_sxyram = SIZEOF(.xyram);
_lgmapped = ABSOLUTE(0);
_sgmapped = ABSOLUTE(0);
_lreloc = ABSOLUTE(0);
_sreloc = ABSOLUTE(0);
_gint_region_vbr = ORIGIN(vbr);
/* BSS data going to RAM. The BSS section is to be stripped from the
ELF file later, and wiped at startup */
.bss (NOLOAD) : {
_rbss = . ;
*(.bss .bss.* COMMON)
. = ALIGN(16);
} > ram :NONE
_sbss = SIZEOF(.bss);
/* gint's uninitialized BSS section, going to static RAM. All the large
data arrays will be located here */
.gint.bss (NOLOAD) : {
*(.gint.bss)
. = ALIGN(16);
/* End of user RAM */
_euram = . ;
} > ram :NONE
_sgbss = SIZEOF(.gint.bss);
/*
** Unused sections
*/
/DISCARD/ : {
/* SH3-only data sections */
*(.gint.rodata.sh3 .gint.data.sh3 .gint.bss.sh3)
/* Java class registration (why are they even here?!) */
*(.jcr)
/* Asynchronous unwind tables: no C++ exception handling */
*(.eh_frame_hdr)
*(.eh_frame)
/* Comments or anything the compiler might generate */
*(.comment)
}
}

View file

@ -18,11 +18,18 @@
#if defined(FX9860G) #if defined(FX9860G)
# define GINT_HW_FX 1 # define GINT_HW_FX 1
# define GINT_HW_CG 0 # define GINT_HW_CG 0
# define GINT_HW_SWITCH(FX,CG) (FX) # define GINT_HW_CP 0
# define GINT_HW_SWITCH(FX,CG,CP) (FX)
#elif defined(FXCG50) #elif defined(FXCG50)
# define GINT_HW_FX 0 # define GINT_HW_FX 0
# define GINT_HW_CG 1 # define GINT_HW_CG 1
# define GINT_HW_SWITCH(FX,CG) (CG) # define GINT_HW_CP 0
# define GINT_HW_SWITCH(FX,CG,CP) (CG)
#elif defined(FXCP)
# define GINT_HW_FX 0
# define GINT_HW_CG 0
# define GINT_HW_CP 1
# define GINT_HW_SWITCH(FX,CG,CP) (CP)
#endif #endif
/* Shorthand to simplify definitions below. Won't be needed for long. */ /* Shorthand to simplify definitions below. Won't be needed for long. */
@ -36,6 +43,7 @@
see no reason this would be different from hardware, but who knows. */ see no reason this would be different from hardware, but who knows. */
#define GINT_OS_FX GINT_HW_FX #define GINT_OS_FX GINT_HW_FX
#define GINT_OS_CG GINT_HW_CG #define GINT_OS_CG GINT_HW_CG
#define GINT_OS_CP GINT_HW_CP
#define GINT_OS_SWITCH GINT_HW_SWITCH #define GINT_OS_SWITCH GINT_HW_SWITCH
/* GINT_NO_OS_STACK: Disables using a chunk of the OS stack as a heap. The top /* GINT_NO_OS_STACK: Disables using a chunk of the OS stack as a heap. The top
@ -70,6 +78,6 @@
/* GINT_RENDER_{MONO,RGB}: Enable the mono/rgb rendering API. /* GINT_RENDER_{MONO,RGB}: Enable the mono/rgb rendering API.
Currently these are exclusive. */ Currently these are exclusive. */
#define GINT_RENDER_MONO (GINT_HW_FX || GINT_FX9860G_G3A) #define GINT_RENDER_MONO (GINT_HW_FX || GINT_FX9860G_G3A)
#define GINT_RENDER_RGB (GINT_HW_CG && !GINT_FX9860G_G3A) #define GINT_RENDER_RGB ((GINT_HW_CG || GINT_HW_CP) && !GINT_FX9860G_G3A)
#endif /* GINT_CONFIG */ #endif /* GINT_CONFIG */

View file

@ -25,8 +25,13 @@ extern "C" {
#include <gint/image.h> #include <gint/image.h>
/* Dimensions of the VRAM */ /* Dimensions of the VRAM */
#if GINT_HW_CG
#define DWIDTH 396 #define DWIDTH 396
#define DHEIGHT 224 #define DHEIGHT 224
#elif GINT_HW_CP
#define DWIDTH 320
#define DHEIGHT 528
#endif
/* gint VRAM address. This value must always point to a 32-aligned buffer of /* gint VRAM address. This value must always point to a 32-aligned buffer of
size 177408. Any function can use it freely to perform rendering or store size 177408. Any function can use it freely to perform rendering or store

View file

@ -0,0 +1,26 @@
//---
// gint:drivers:r61523 - Reneses R61523 driver
//
// This driver is used to control the 16-bit color LCD of the fx-CP 400.
//---
#ifndef GINT_DRIVERS_R61523
#define GINT_DRIVERS_R61523
#ifdef __cplusplus
extern "C" {
#endif
#include <gint/defs/types.h>
/* r61523_display(): Update the entire display (320x528) */
void r61523_display(uint16_t *vram);
/* r61523_win_set(): Set the display window */
void r61523_win_set(int x1, int x2, int y1, int y2);
#ifdef __cplusplus
}
#endif
#endif /* GINT_DRIVERS_R61523 */

View file

@ -46,7 +46,7 @@ void hw_detect(void);
# define isSH3() (gint[HWMPU] & 1) # define isSH3() (gint[HWMPU] & 1)
# define isSH4() (!isSH3()) # define isSH4() (!isSH3())
# define isSlim() (gint[HWCALC] == HWCALC_FX9860G_SLIM) # define isSlim() (gint[HWCALC] == HWCALC_FX9860G_SLIM)
#elif GINT_HW_CG #elif GINT_HW_CG || GINT_HW_CP
# define isSH3() 0 # define isSH3() 0
# define isSH4() 1 # define isSH4() 1
# define isSlim() 0 # define isSlim() 0
@ -109,6 +109,8 @@ void hw_detect(void);
#define HWCALC_FXCG_MANAGER 6 #define HWCALC_FXCG_MANAGER 6
/* fx-9860G Slim, SH-3-based fx-9860G with hardware differences */ /* fx-9860G Slim, SH-3-based fx-9860G with hardware differences */
#define HWCALC_FX9860G_SLIM 7 #define HWCALC_FX9860G_SLIM 7
/* fx-CP 400 */
#define HWCALC_FXCP400 8
/* /*
** Keyboard ** Keyboard

View file

@ -29,8 +29,10 @@ typedef struct {
} video_mode_t; } video_mode_t;
/* Flags for the update function of the interface. */ /* Flags for the update function of the interface. */
#define VIDEO_UPDATE_ENABLE_DMA 0x01 #define VIDEO_UPDATE_NONE 0x00
#define VIDEO_UPDATE_ATOMIC 0x02 #define VIDEO_UPDATE_ENABLE_DMA 0x01
#define VIDEO_UPDATE_ATOMIC 0x02
#define VIDEO_UPDATE_FOREIGN_WORLD 0x04
/* Video driver interface. */ /* Video driver interface. */
typedef struct { typedef struct {

View file

@ -104,7 +104,7 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
dtext(6, 3, "An exception occured! (System ERROR)"); dtext(6, 3, "An exception occured! (System ERROR)");
uint32_t *long_vram = (void *)gint_vram; uint32_t *long_vram = (void *)gint_vram;
for(int i = 0; i < 198 * 16; i++) long_vram[i] = ~long_vram[i]; for(int i = 0; i < (DWIDTH/2) * 16; i++) long_vram[i] = ~long_vram[i];
char const *name = ""; char const *name = "";
if(code == 0x040) name = "TLB miss (nonexisting address) on read"; if(code == 0x040) name = "TLB miss (nonexisting address) on read";
@ -126,20 +126,25 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
dtext(6, 45, "PC"); dtext(6, 45, "PC");
dprint(38, 45, "= %08x", PC); dprint(38, 45, "= %08x", PC);
dtext(261, 45, "(Error location)"); dtext(DWIDTH-135, 45, "(Error location)");
dtext(6, 60, "TEA"); dtext(6, 60, "TEA");
dprint(38, 60, "= %08x", TEA); dprint(38, 60, "= %08x", TEA);
dtext(234, 60, "(Offending address)"); dtext(DWIDTH-162, 60, "(Offending address)");
dtext(6, 75, "TRA"); dtext(6, 75, "TRA");
dprint(38, 75, "= %#x", TRA); dprint(38, 75, "= %#x", TRA);
dtext(281, 75, "(Trap number)"); dtext(DWIDTH-115, 75, "(Trap number)");
dtext(6, 95, "The add-in crashed!"); dtext(6, 95, "The add-in crashed!");
if(kd == NULL) { if(kd == NULL) {
#if GINT_HW_CG
dtext(6, 108, "Please press the RESET button to restart the"); dtext(6, 108, "Please press the RESET button to restart the");
dtext(6, 121, "calculator."); dtext(6, 121, "calculator.");
#else
dtext(6, 108, "Please press the RESET button to");
dtext(6, 121, "restart the calculator.");
#endif
} }
else { else {
dtext(6, 121, "[EXIT]: Exit the program with abort()"); dtext(6, 121, "[EXIT]: Exit the program with abort()");

View file

@ -145,6 +145,25 @@ void hw_detect(void)
utlb_mapped_memory(NULL, NULL); utlb_mapped_memory(NULL, NULL);
} }
#elif GINT_HW_CP
/* hw_detect(): Basic hardware detection */
void hw_detect(void)
{
gint[HWMPU] = HWMPU_SH7305;
gint[HWCPUVR] = PVR;
gint[HWCPUPR] = PRR;
gint[HWCALC] = HWCALC_FXCP400;
// TODO: What filesystem implementation on the fx-CP 400?
gint[HWFS] = HWFS_NONE;
gint[HWRAM] = 16 << 20;
// TOOD: How much ROM on the fx-CP 400?
gint[HWROM] = 0;
/* There is no userspace so not MMU being used */
gint[HWURAM] = 0;
}
#else #else
#error unknown hardware type for hw_detect #error unknown hardware type for hw_detect
#endif #endif

View file

@ -40,8 +40,6 @@ void *gint_stack_top = NULL;
/* kinit(): Install and start gint */ /* kinit(): Install and start gint */
void kinit(void) void kinit(void)
{ {
uint32_t VBR = 0;
#if GINT_HW_FX #if GINT_HW_FX
/* On fx-9860G, VBR is loaded at the end of the user RAM. On SH4, the /* On fx-9860G, VBR is loaded at the end of the user RAM. On SH4, the
end of the user RAM hosts the stack, for which we leave 12 kB end of the user RAM hosts the stack, for which we leave 12 kB
@ -59,7 +57,7 @@ void kinit(void)
/* VBR is advanced 0x100 bytes because of an unused gap */ /* VBR is advanced 0x100 bytes because of an unused gap */
uram_end -= (isSH3() ? 0x600 : 0x1100); uram_end -= (isSH3() ? 0x600 : 0x1100);
VBR = uram_end - 0x100; uint32_t VBR = uram_end - 0x100;
#endif #endif
#if GINT_HW_CG #if GINT_HW_CG
@ -67,11 +65,16 @@ void kinit(void)
script leaves 5 kB (0x1400 bytes) before the start of the data script leaves 5 kB (0x1400 bytes) before the start of the data
segment. The stack is again placed at the end of the region, and we segment. The stack is again placed at the end of the region, and we
leave 16 kB. */ leave 16 kB. */
VBR = (uint32_t)mmu_uram(); uint32_t VBR = (uint32_t)mmu_uram();
uint32_t uram_end = (uint32_t)mmu_uram() + mmu_uram_size() - 0x4000; uint32_t uram_end = (uint32_t)mmu_uram() + mmu_uram_size() - 0x4000;
gint_stack_top = (void *)uram_end; gint_stack_top = (void *)uram_end;
#endif #endif
#if GINT_HW_CP
extern char gint_region_vbr;
uint32_t VBR = (uint32_t)&gint_region_vbr - 0x100;
#endif
/* Event handler entry points */ /* Event handler entry points */
void *inth_entry = isSH3() ? gint_inth_7705 : gint_inth_7305; void *inth_entry = isSH3() ? gint_inth_7705 : gint_inth_7305;
uint32_t exch_size = (uint32_t)&gint_exch_size; uint32_t exch_size = (uint32_t)&gint_exch_size;
@ -85,6 +88,7 @@ void kinit(void)
/* Initialize memory allocators */ /* Initialize memory allocators */
kmalloc_init(); kmalloc_init();
#if !GINT_HW_CP
/* Create an allocation arena with unused static RAM */ /* Create an allocation arena with unused static RAM */
static kmalloc_arena_t static_ram = { 0 }; static kmalloc_arena_t static_ram = { 0 };
extern uint32_t euram; extern uint32_t euram;
@ -94,6 +98,7 @@ void kinit(void)
static_ram.end = (void *)uram_end; static_ram.end = (void *)uram_end;
kmalloc_init_arena(&static_ram, true); kmalloc_init_arena(&static_ram, true);
kmalloc_add_arena(&static_ram); kmalloc_add_arena(&static_ram);
#endif
/* Create an arena in the OS stack as well, for VRAM and more data */ /* Create an arena in the OS stack as well, for VRAM and more data */
#if GINT_HW_CG && !defined(GINT_NO_OS_STACK) #if GINT_HW_CG && !defined(GINT_NO_OS_STACK)
@ -143,6 +148,11 @@ void kquit(void)
{ {
gint_world_switch_out(gint_world_addin, gint_world_os); gint_world_switch_out(gint_world_addin, gint_world_os);
#if !GINT_OS_FX
extern void dvram_quit(void);
dvram_quit();
#endif
gint_world_free(gint_world_os); gint_world_free(gint_world_os);
gint_world_free(gint_world_addin); gint_world_free(gint_world_addin);
free(gint_driver_flags); free(gint_driver_flags);

View file

@ -16,6 +16,7 @@ void __ClearKeyBuffer(void); /* ? */
void __ConfigureStatusArea(int mode); void __ConfigureStatusArea(int mode);
void __SetQuitHandler(void (*callback)(void)); void __SetQuitHandler(void (*callback)(void));
#if !GINT_OS_CP
static int __osmenu_id; static int __osmenu_id;
static void __osmenu_handler(void) static void __osmenu_handler(void)
@ -28,6 +29,7 @@ static void __osmenu_handler(void)
__Timer_Stop(__osmenu_id); __Timer_Stop(__osmenu_id);
__Timer_Deinstall(__osmenu_id); __Timer_Deinstall(__osmenu_id);
} }
#endif
#if GINT_OS_CG #if GINT_OS_CG
typedef void (os_menu_function_t)(void); typedef void (os_menu_function_t)(void);
@ -94,6 +96,8 @@ static os_menu_function_t *find_os_menu_function(void)
void gint_osmenu_native(void) void gint_osmenu_native(void)
{ {
// TODO: OS menu on fx-CP
#if !GINT_OS_CP
__ClearKeyBuffer(); __ClearKeyBuffer();
gint_copy_vram(); gint_copy_vram();
@ -134,6 +138,7 @@ void gint_osmenu_native(void)
1 /* Delay in seconds */, 1 /* Delay in seconds */,
0 /* Enable return to main menu */, 0 /* Enable return to main menu */,
&keycode); &keycode);
#endif
} }
/* gint_osmenu() - switch out of gint and call the calculator's main menu */ /* gint_osmenu() - switch out of gint and call the calculator's main menu */
@ -157,7 +162,11 @@ static void __handler()
static void __sethandler() static void __sethandler()
{ {
(void)__handler;
// TODO: Quit handler on fx-CP
#if !GINT_OS_CP
__SetQuitHandler((void *)__handler); __SetQuitHandler((void *)__handler);
#endif
} }
void gint_set_quit_handler(gint_call_t gcall, bool do_world_switch) void gint_set_quit_handler(gint_call_t gcall, bool do_world_switch)

18
src/kernel/start.S Normal file
View file

@ -0,0 +1,18 @@
#include <gint/config.h>
#if GINT_OS_CP
.section .text.header
.global _start_header
_start_header:
mov.l .start, r0
jmp @r0
nop
.align 2
.start:
.long _start
.load_addr:
.long _start_header
#endif

View file

@ -151,11 +151,14 @@ static int start2(int isappli, int optnum)
/* Load data sections and wipe the bss section. This has to be done /* Load data sections and wipe the bss section. This has to be done
first for static and global variables to be initialized */ first for static and global variables to be initialized */
regcpy(&ldata, &sdata, &rdata); #if !GINT_OS_CP
regcpy(&ldata, &sdata, &rdata);
#endif
regclr(&rbss, &sbss); regclr(&rbss, &sbss);
gint_load_onchip_sections(); gint_load_onchip_sections();
#if !GINT_OS_CP
/* Copy permanently-mapped code to start of user RAM (this section is /* Copy permanently-mapped code to start of user RAM (this section is
only used on fx-9860G; on fx-CG 50 it's fixed in ILRAM) */ only used on fx-9860G; on fx-CG 50 it's fixed in ILRAM) */
void *rgmapped = mmu_uram(); void *rgmapped = mmu_uram();
@ -167,6 +170,7 @@ static int start2(int isappli, int optnum)
{ {
fixups[i] += (uint32_t)rgmapped; fixups[i] += (uint32_t)rgmapped;
} }
#endif
/* Install gint, switch VBR and initialize drivers */ /* Install gint, switch VBR and initialize drivers */
kinit(); kinit();

View file

@ -45,6 +45,9 @@
.global ___GetVRAMAddress .global ___GetVRAMAddress
.global ___ConfigureStatusArea .global ___ConfigureStatusArea
.global ___SetQuitHandler .global ___SetQuitHandler
/* VRAM backup on fx-CP */
.global ___VRAMBackup
.global ___VRAMRestore
/* Reset */ /* Reset */
.global ___PowerOff .global ___PowerOff
@ -55,11 +58,18 @@
mov.l 1f, r0 ;\ mov.l 1f, r0 ;\
jmp @r2 ;\ jmp @r2 ;\
nop ;\ nop ;\
.align 4 ;\ .balign 4 ;\
1: .long id 1: .long id
#define syscall(id) syscall_(id, syscall_table) #define syscall(id) syscall_(id, syscall_table)
#define fixed(address) \
mov.l 1f, r0 ;\
jmp @r0 ;\
nop ;\
.balign 4 ;\
1: .long address
#if GINT_OS_FX #if GINT_OS_FX
/* Dynamic allocation */ /* Dynamic allocation */
@ -212,3 +222,26 @@ syscall_table:
.long 0x80020070 .long 0x80020070
#endif /* GINT_OS_CG */ #endif /* GINT_OS_CG */
#if GINT_OS_CP
___malloc:
fixed(0x800cfb00)
___realloc:
// TODO: realloc for fx-CP?
rts
mov #0, r0
___free:
fixed(0x800a76fc)
___GetVRAMAddress:
fixed(0x8002e154)
___VRAMBackup:
fixed(0x8002d3fa)
___VRAMRestore:
fixed(0x8002d41a)
___Reset:
fixed(0xa0000000)
#endif /* GINT_OS_CP */

View file

@ -10,11 +10,14 @@
#elif GINT_OS_CG #elif GINT_OS_CG
# define SYSCALL_TABLE 0x80020070 # define SYSCALL_TABLE 0x80020070
# define SYSCALL_TLBH 12 # define SYSCALL_TLBH 12
#elif GINT_OS_CP
# define NOMMU 1
#else #else
# error Unknown HW for tlbh.S! # error Unknown HW for tlbh.S!
#endif #endif
_gint_tlbh: _gint_tlbh:
#if ! NOMMU
sts.l pr, @-r15 sts.l pr, @-r15
stc.l gbr, @-r15 stc.l gbr, @-r15
sts.l mach, @-r15 sts.l mach, @-r15
@ -50,10 +53,12 @@ map:
lds.l @r15+, pr lds.l @r15+, pr
rte rte
nop nop
#endif
panic: panic:
/* Otherwise, panic by defaulting to the exception handler (the TLB /* Otherwise, or if there is no MMU, panic by defaulting to the
miss may still be resolved by a panic handler) */ exception handler (the TLB miss may still be resolved by a panic
handler) */
lds.l @r15+, macl lds.l @r15+, macl
lds.l @r15+, mach lds.l @r15+, mach
ldc.l @r15+, gbr ldc.l @r15+, gbr
@ -66,6 +71,7 @@ panic:
jmp @r0 jmp @r0
nop nop
#if ! NOMMU
.align 4 .align 4
.gint: .gint:
@ -80,3 +86,4 @@ panic:
.long 0x00300000 + _srom .long 0x00300000 + _srom
.syscall: .syscall:
.long SYSCALL_TABLE .long SYSCALL_TABLE
#endif

View file

@ -244,9 +244,12 @@ void gint_copy_vram(void)
#endif #endif
} }
void gint_poweroff(bool show_logo) void gint_poweroff(GUNUSED bool show_logo)
{ {
// TODO: Power off on fx-CP
#if !GINT_OS_CP
void __PowerOff(int show_logo); void __PowerOff(int show_logo);
gint_copy_vram(); gint_copy_vram();
gint_world_switch(GINT_CALL(__PowerOff, (int)show_logo)); gint_world_switch(GINT_CALL(__PowerOff, (int)show_logo));
#endif
} }

183
src/r61523/r61523.c Normal file
View file

@ -0,0 +1,183 @@
// Renesas R61523 driver-
#include <gint/defs/types.h>
#include <gint/defs/util.h>
// #include <gint/hardware.h>
#include <gint/drivers.h>
// #include <gint/dma.h>
#include <gint/drivers/r61523.h>
#include <gint/video.h>
#include <gint/image.h>
#include <gint/config.h>
#if GINT_HW_CP
/* Registers */
#define REG_HRANGE 0x2a
#define REG_VRANGE 0x2b
#define REG_DATA 0x2c
#define REG_DEVICE_CODE_READ 0xbf
/* Interface with the controller */
static volatile uint16_t *DISPLAY = (void *)0xb4000000;
/* Bit 4 of Port R controls the RS bit of the display driver */
static volatile uint8_t *PRDR = (void *)0xa405013c;
/* Select a register */
GINLINE static void select(uint16_t reg)
{
/* Clear RS and write the register number */
*PRDR &= ~0x10;
synco();
*DISPLAY = reg;
synco();
/* Set RS=1 to allow consecutive reads/writes after a select() */
*PRDR |= 0x10;
synco();
}
GINLINE static void write(uint16_t data)
{
*DISPLAY = data;
}
GINLINE static uint16_t read(void)
{
return *DISPLAY;
}
static void read_Nu16(uint16_t *array, int N)
{
for(int i = 0; i < N; i++)
array[i] = *DISPLAY;
}
//---
// Generic functions
//---
void r61523_identify(uint32_t *manufacturerCode, uint16_t *deviceCode)
{
select(REG_DEVICE_CODE_READ);
uint16_t packets[5];
read_Nu16(packets, 5);
if(manufacturerCode)
*manufacturerCode = (packets[1] << 16) | packets[2];
if(deviceCode)
*deviceCode = (packets[3] << 16) | packets[4];
}
//---
// Window management
//---
void r61523_win_set(int x1, int x2, int y1, int y2)
{
/* R61523 has a 360x640 area; the CP-400 uses the top-right corner for its
320x528 display, so skip over the first 40 columns */
x1 += 40;
x2 += 40;
uint16_t volatile *DISPLAY = (void *)0xb4000000;
select(REG_HRANGE);
/* Upper half has 2 bits (total 10 bits = 1024) */
*DISPLAY = (x1 >> 8) & 3;
synco();
*DISPLAY = x1 & 0xff;
*DISPLAY = (x2 >> 8) & 3;
synco();
*DISPLAY = x2 & 0xff;
synco();
select(REG_VRANGE);
*DISPLAY = (y1 >> 8) & 3;
synco();
*DISPLAY = y1 & 0xff;
synco();
*DISPLAY = (y2 >> 8) & 3;
synco();
*DISPLAY = y2 & 0xff;
synco();
}
void r61523_display(uint16_t *vram)
{
r61523_win_set(0, 319, 0, 527);
select(44);
int row_offset = 0;
uint16_t volatile *DISPLAY = (void *)0xb4000000;
for(int y = 0; y < 528; y++) {
uint16_t *r5 = (void *)vram + row_offset;
for(int x = 0; x < 320; x++)
*DISPLAY = *r5++;
row_offset += 2 * 320;
}
}
static bool r61523_update(int x, int y, image_t const *fb, int flags)
{
if(fb->format != IMAGE_RGB565)
return false;
// TODO: r61523_update: DMA support
// unless VIDEO_UPDATE_FOREIGN_WORLD is set
(void)flags;
uint w = fb->width;
uint h = fb->height;
// TODO: r61523_update: sub-rectangle support
if(x != 0 || y != 0 || w != 320 || h != 528)
return false;
// TODO: r61523_update: stride support!
if(fb->stride != 320 * 2)
return false;
r61523_display(fb->data);
return true;
}
//---
// Driver metadata
//---
/* As far as I can tell there's no way to read the current window from the
controller so this driver is completely stateless for now. */
gint_driver_t drv_r61523 = {
.name = "R61523",
};
GINT_DECLARE_DRIVER(26, drv_r61523);
//---
// Video driver interface
//---
static video_mode_t r61523_modes[] = {
/* Standard full-screen full-color mode */
{ 320, 528, IMAGE_RGB565, -1 },
{ 0 }
};
video_interface_t r61523_video = {
.driver = &drv_r61523,
.modes = r61523_modes,
.mode_get = NULL, // TODO
.mode_set = NULL, // TODO
.brightness_min = 0, // TODO
.brightness_max = 0, // TODO
.brightness_set = NULL,
.update = r61523_update,
};
#endif /* GINT_HW_CP */

View file

@ -5,6 +5,11 @@
void dclear(uint16_t color) void dclear(uint16_t color)
{ {
// TODO: CP: DMA support for dclear()
#if GINT_HW_CP
for(int i = 0; i < DWIDTH * DHEIGHT; i++)
gint_vram[i] = color;
#else
bool full_width = (dwindow.left == 0 && dwindow.right == DWIDTH); bool full_width = (dwindow.left == 0 && dwindow.right == DWIDTH);
bool dma_aligned = !(dwindow.top & 3) && !(dwindow.bottom & 3); bool dma_aligned = !(dwindow.top & 3) && !(dwindow.bottom & 3);
@ -17,6 +22,7 @@ void dclear(uint16_t color)
drect(dwindow.left, dwindow.top, dwindow.right - 1, drect(dwindow.left, dwindow.top, dwindow.right - 1,
dwindow.bottom - 1, color); dwindow.bottom - 1, color);
} }
#endif
} }
#endif #endif

View file

@ -1,9 +1,20 @@
#include <gint/display.h> #include <gint/display.h>
#include <gint/drivers/r61523.h>
#include <gint/drivers/r61524.h> #include <gint/drivers/r61524.h>
#include "render-cg.h" #include "render-cg.h"
#include <gint/config.h> #include <gint/config.h>
#if GINT_RENDER_RGB #if GINT_RENDER_RGB
#if GINT_HW_CP
void dupdate(void)
{
r61523_display(gint_vram);
gint_call(dupdate_get_hook());
}
#elif GINT_HW_CG
/* dupdate(): Push the video RAM to the display driver */ /* dupdate(): Push the video RAM to the display driver */
void dupdate(void) void dupdate(void)
{ {
@ -19,7 +30,10 @@ void dupdate(void)
/* Switch buffers if triple buffering is enabled */ /* Switch buffers if triple buffering is enabled */
dvram_switch(); dvram_switch();
} }
#endif
__attribute__((alias("dupdate"))) __attribute__((alias("dupdate")))
void _WEAK_dupdate(void); void _WEAK_dupdate(void);
#endif #endif /* GINT_RENDER_RGB */

View file

@ -1,8 +1,37 @@
#include <gint/display.h> #include <gint/display.h>
#include <gint/kmalloc.h> #include <gint/kmalloc.h>
#include <gint/video.h>
#include <gint/image.h>
#include <gint/config.h> #include <gint/config.h>
#if GINT_RENDER_RGB #if GINT_RENDER_RGB
#if GINT_OS_CP
extern void *__GetVRAMAddress(void);
extern void __VRAMBackup(void);
extern void __VRAMRestore(void);
uint16_t *gint_vram = NULL;
bool dvram_init(void)
{
__VRAMBackup();
gint_vram = __GetVRAMAddress();
return true;
}
void dvram_quit(void)
{
__VRAMRestore();
// TODO: CP dvram_quit: use global framebuffer image
image_t *img = image_create_vram();
video_update(0, 0, img, VIDEO_UPDATE_FOREIGN_WORLD);
image_free(img);
}
#elif GINT_OS_CG
// TODO[3]: CG: Remove triple buffering
/* Up to two VRAM pointers can be set, for triple buffering. */ /* Up to two VRAM pointers can be set, for triple buffering. */
static uint16_t *vram_1 = NULL, *vram_2 = NULL; static uint16_t *vram_1 = NULL, *vram_2 = NULL;
/* Current VRAM pointer, always equal to either vram_1 or vram_2. */ /* Current VRAM pointer, always equal to either vram_1 or vram_2. */
@ -69,4 +98,9 @@ void dvram_switch(void)
gint_vram = (gint_vram == vram_1) ? vram_2 : vram_1; gint_vram = (gint_vram == vram_1) ? vram_2 : vram_1;
} }
#endif void dvram_quit(void)
{
}
#endif /* OS type */
#endif /* GINT_RENDER_RGB */

View file

@ -1,5 +1,11 @@
#include <gint/config.h> #include <gint/config.h>
#if GINT_RENDER_RGB #if GINT_RENDER_RGB
// TODO: topti-asm: avoid duplicating DWIDTH here
#if GINT_HW_CG
# define DWIDTH 396
#elif GINT_HW_CP
# define DWIDTH 320
#endif
.global _topti_glyph_fg_bg .global _topti_glyph_fg_bg
.global _topti_glyph_fg .global _topti_glyph_fg
@ -39,7 +45,7 @@
_topti_glyph_fg_bg: _topti_glyph_fg_bg:
# Compute VRAM stride 2 * (396-width) # Compute VRAM stride 2 * (DWIDTH-width)
mov.l r8, @-r15 mov.l r8, @-r15
mov.l 1f, r8 mov.l 1f, r8
mov.l @(4, r15), r3 mov.l @(4, r15), r3
@ -96,7 +102,7 @@ _topti_glyph_fg_bg:
_topti_glyph_fg: _topti_glyph_fg:
# Compute VRAM stride 2 * (396-width) # Compute VRAM stride 2 * (DWIDTH-width)
mov.l r8, @-r15 mov.l r8, @-r15
mov.l 1f, r8 mov.l 1f, r8
mov.l @(4, r15), r3 mov.l @(4, r15), r3
@ -149,7 +155,7 @@ _topti_glyph_fg:
_topti_glyph_bg: _topti_glyph_bg:
# Compute VRAM stride 2 * (396-width) # Compute VRAM stride 2 * (DWIDTH-width)
mov.l r8, @-r15 mov.l r8, @-r15
mov.l 1f, r8 mov.l 1f, r8
mov.l @(4, r15), r3 mov.l @(4, r15), r3
@ -202,6 +208,6 @@ _topti_glyph_bg:
.align 4 .align 4
1: .long 396*2 1: .long DWIDTH*2
#endif #endif

View file

@ -178,6 +178,7 @@ static char const * const str_CALC[] = {
[HWCALC_FXCG50] = "fx-CG 50/Graph 90+E", [HWCALC_FXCG50] = "fx-CG 50/Graph 90+E",
[HWCALC_FXCG_MANAGER] = "fx-CG Manager", [HWCALC_FXCG_MANAGER] = "fx-CG Manager",
[HWCALC_FX9860G_SLIM] = "fx-9860G Slim", [HWCALC_FX9860G_SLIM] = "fx-9860G Slim",
[HWCALC_FXCP400] = "fx-CP 400",
}; };
static void execute_command(char const *cmd) static void execute_command(char const *cmd)
@ -191,7 +192,7 @@ static void execute_command(char const *cmd)
char const *serial_number = (void *)0x8000ffd0; char const *serial_number = (void *)0x8000ffd0;
char const *OS_version = (void *)0x80010020; char const *OS_version = (void *)0x80010020;
char const *BC_version = (void *)0x8000ffb0; char const *BC_version = (void *)0x8000ffb0;
#elif GINT_OS_CG #elif GINT_OS_CG || GINT_OS_CP
char const *serial_number = (void *)0x8001ffd0; char const *serial_number = (void *)0x8001ffd0;
char const *OS_version = (void *)0x80020020; char const *OS_version = (void *)0x80020020;
char const *BC_version = (void *)0x8001ffb0; char const *BC_version = (void *)0x8001ffb0;

View file

@ -17,10 +17,11 @@
/* 0x6101: fx-9860G II, Protocol 7.00, etc. /* 0x6101: fx-9860G II, Protocol 7.00, etc.
0x6102: fx-CP 400, fx-CG 50, Mass Storage, etc. */ 0x6102: fx-CP 400, fx-CG 50, Mass Storage, etc. */
#define ID_PRODUCT GINT_HW_SWITCH(0x6101, 0x6102) #define ID_PRODUCT GINT_HW_SWITCH(0x6101, 0x6102, 0x6102)
#define DESC_PRODUCT GINT_HW_SWITCH( \ #define DESC_PRODUCT GINT_HW_SWITCH( \
u"CASIO fx-9860G family on gint", \ u"CASIO fx-9860G family on gint", \
u"CASIO fx-CG family on gint") u"CASIO fx-CG family on gint", \
u"CASIO fx-CP family on gint")
static usb_dc_device_t dc_device = { static usb_dc_device_t dc_device = {
.bLength = sizeof(usb_dc_device_t), .bLength = sizeof(usb_dc_device_t),
@ -56,7 +57,8 @@ static usb_dc_string_t dc_string0 = {
GCONSTRUCTOR static void set_strings(void) GCONSTRUCTOR static void set_strings(void)
{ {
char const *serial_base = (void *)GINT_OS_SWITCH(0x8000ffd0, 0x8001ffd0); char const *serial_base =
(void *)GINT_OS_SWITCH(0x8000ffd0, 0x8001ffd0, 0x8001ffd0);
/* Convert the serial number to UTF-16 */ /* Convert the serial number to UTF-16 */
uint16_t serial[8]; uint16_t serial[8];

View file

@ -2,10 +2,10 @@
#include <gint/config.h> #include <gint/config.h>
// TODO: video: Have interface set by gint pre-main call instead // TODO: video: Have interface set by gint pre-main call instead
extern video_interface_t t6k11_video, r61524_video; extern video_interface_t t6k11_video, r61524_video, r61523_video;
static video_interface_t const *current_intf = static video_interface_t const *current_intf =
GINT_HW_SWITCH(NULL, &r61524_video); GINT_HW_SWITCH(NULL, &r61524_video, &r61523_video);
static int current_mode_index = GINT_HW_SWITCH(-1, 0); static int current_mode_index = GINT_HW_SWITCH(-1, 0, 0);
video_interface_t const *video_get_current_interface(void) video_interface_t const *video_get_current_interface(void)
{ {