mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-26 19:43:35 +01:00
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:
parent
5c3dc3220a
commit
789ba7caa5
26 changed files with 657 additions and 38 deletions
|
@ -124,6 +124,7 @@ set(SOURCES
|
|||
src/kernel/kernel.c
|
||||
src/kernel/osmenu.c
|
||||
src/kernel/start.c
|
||||
src/kernel/start.S
|
||||
src/kernel/syscalls.S
|
||||
src/kernel/tlbh.S
|
||||
src/kernel/world.c
|
||||
|
@ -144,6 +145,8 @@ set(SOURCES
|
|||
src/kmalloc/kmalloc.c
|
||||
# MMU driver
|
||||
src/mmu/mmu.c
|
||||
# R61523 display driver
|
||||
src/r61523/r61523.c
|
||||
# R61524 display driver
|
||||
src/r61524/r61524.c
|
||||
# Format-agnostic rendering
|
||||
|
@ -250,6 +253,7 @@ set(SOURCES
|
|||
|
||||
set(ASSETS_FX src/font5x7.png src/gdb/icons-i1msb.png)
|
||||
set(ASSETS_CG src/font8x9.png src/gdb/icons-rgb565.png)
|
||||
set(ASSETS_CP ${ASSETS_CG})
|
||||
fxconv_declare_assets(${ASSETS_FX} ${ASSETS_CG})
|
||||
|
||||
include_directories(
|
||||
|
@ -283,6 +287,14 @@ if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_G3A)
|
|||
add_library(${NAME} STATIC ${SOURCES} ${ASSETS_FX} ${LINKER_SCRIPTS})
|
||||
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}")
|
||||
|
||||
# Generate linker scripts
|
||||
|
@ -296,6 +308,7 @@ endmacro()
|
|||
generate_linker_script("fx9860g.ld" "fx9860g.ld.c" "")
|
||||
generate_linker_script("fxcg50.ld" "fxcg50.ld.c" "")
|
||||
generate_linker_script("fxcg50_fastload.ld" "fxcg50.ld.c" "-DFXCG50_FASTLOAD")
|
||||
generate_linker_script("fxcp_hh2.ld" "fxcp_hh2.ld.c" "")
|
||||
|
||||
# Library file
|
||||
install(TARGETS "${NAME}" DESTINATION "${FXSDK_LIB}")
|
||||
|
|
26
TODO
26
TODO
|
@ -25,9 +25,6 @@ Future directions:
|
|||
* Make fx9860g projects work out of the box on fxcg50
|
||||
* 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:
|
||||
- display: Toggle backlight (or set level)
|
||||
-> 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
|
||||
pair of I1MSB buffers, the first being bit #0, the second bit #1. */
|
||||
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
|
||||
|
|
|
@ -11,6 +11,10 @@ elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_G3A)
|
|||
set(PC fxg3a)
|
||||
set(INTF_DEFN FX9860G_G3A)
|
||||
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()
|
||||
message(FATAL_ERROR "gint: unknown fxSDK platform '${FXSDK_PLATFORM}'")
|
||||
endif()
|
||||
|
|
189
fxcp_hh2.ld.c
Normal file
189
fxcp_hh2.ld.c
Normal 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)
|
||||
}
|
||||
}
|
|
@ -18,11 +18,18 @@
|
|||
#if defined(FX9860G)
|
||||
# define GINT_HW_FX 1
|
||||
# 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)
|
||||
# define GINT_HW_FX 0
|
||||
# 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
|
||||
|
||||
/* 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. */
|
||||
#define GINT_OS_FX GINT_HW_FX
|
||||
#define GINT_OS_CG GINT_HW_CG
|
||||
#define GINT_OS_CP GINT_HW_CP
|
||||
#define GINT_OS_SWITCH GINT_HW_SWITCH
|
||||
|
||||
/* 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.
|
||||
Currently these are exclusive. */
|
||||
#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 */
|
||||
|
|
|
@ -25,8 +25,13 @@ extern "C" {
|
|||
#include <gint/image.h>
|
||||
|
||||
/* Dimensions of the VRAM */
|
||||
#if GINT_HW_CG
|
||||
#define DWIDTH 396
|
||||
#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
|
||||
size 177408. Any function can use it freely to perform rendering or store
|
||||
|
|
26
include/gint/drivers/r61523.h
Normal file
26
include/gint/drivers/r61523.h
Normal 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 */
|
|
@ -46,7 +46,7 @@ void hw_detect(void);
|
|||
# define isSH3() (gint[HWMPU] & 1)
|
||||
# define isSH4() (!isSH3())
|
||||
# define isSlim() (gint[HWCALC] == HWCALC_FX9860G_SLIM)
|
||||
#elif GINT_HW_CG
|
||||
#elif GINT_HW_CG || GINT_HW_CP
|
||||
# define isSH3() 0
|
||||
# define isSH4() 1
|
||||
# define isSlim() 0
|
||||
|
@ -109,6 +109,8 @@ void hw_detect(void);
|
|||
#define HWCALC_FXCG_MANAGER 6
|
||||
/* fx-9860G Slim, SH-3-based fx-9860G with hardware differences */
|
||||
#define HWCALC_FX9860G_SLIM 7
|
||||
/* fx-CP 400 */
|
||||
#define HWCALC_FXCP400 8
|
||||
|
||||
/*
|
||||
** Keyboard
|
||||
|
|
|
@ -29,8 +29,10 @@ typedef struct {
|
|||
} video_mode_t;
|
||||
|
||||
/* Flags for the update function of the interface. */
|
||||
#define VIDEO_UPDATE_ENABLE_DMA 0x01
|
||||
#define VIDEO_UPDATE_ATOMIC 0x02
|
||||
#define VIDEO_UPDATE_NONE 0x00
|
||||
#define VIDEO_UPDATE_ENABLE_DMA 0x01
|
||||
#define VIDEO_UPDATE_ATOMIC 0x02
|
||||
#define VIDEO_UPDATE_FOREIGN_WORLD 0x04
|
||||
|
||||
/* Video driver interface. */
|
||||
typedef struct {
|
||||
|
|
|
@ -104,7 +104,7 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
|
|||
dtext(6, 3, "An exception occured! (System ERROR)");
|
||||
|
||||
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 = "";
|
||||
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");
|
||||
dprint(38, 45, "= %08x", PC);
|
||||
dtext(261, 45, "(Error location)");
|
||||
dtext(DWIDTH-135, 45, "(Error location)");
|
||||
|
||||
dtext(6, 60, "TEA");
|
||||
dprint(38, 60, "= %08x", TEA);
|
||||
dtext(234, 60, "(Offending address)");
|
||||
dtext(DWIDTH-162, 60, "(Offending address)");
|
||||
|
||||
dtext(6, 75, "TRA");
|
||||
dprint(38, 75, "= %#x", TRA);
|
||||
dtext(281, 75, "(Trap number)");
|
||||
dtext(DWIDTH-115, 75, "(Trap number)");
|
||||
|
||||
dtext(6, 95, "The add-in crashed!");
|
||||
if(kd == NULL) {
|
||||
#if GINT_HW_CG
|
||||
dtext(6, 108, "Please press the RESET button to restart the");
|
||||
dtext(6, 121, "calculator.");
|
||||
#else
|
||||
dtext(6, 108, "Please press the RESET button to");
|
||||
dtext(6, 121, "restart the calculator.");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
dtext(6, 121, "[EXIT]: Exit the program with abort()");
|
||||
|
|
|
@ -145,6 +145,25 @@ void hw_detect(void)
|
|||
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
|
||||
#error unknown hardware type for hw_detect
|
||||
#endif
|
||||
|
|
|
@ -40,8 +40,6 @@ void *gint_stack_top = NULL;
|
|||
/* kinit(): Install and start gint */
|
||||
void kinit(void)
|
||||
{
|
||||
uint32_t VBR = 0;
|
||||
|
||||
#if GINT_HW_FX
|
||||
/* 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
|
||||
|
@ -59,7 +57,7 @@ void kinit(void)
|
|||
|
||||
/* VBR is advanced 0x100 bytes because of an unused gap */
|
||||
uram_end -= (isSH3() ? 0x600 : 0x1100);
|
||||
VBR = uram_end - 0x100;
|
||||
uint32_t VBR = uram_end - 0x100;
|
||||
#endif
|
||||
|
||||
#if GINT_HW_CG
|
||||
|
@ -67,11 +65,16 @@ void kinit(void)
|
|||
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
|
||||
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;
|
||||
gint_stack_top = (void *)uram_end;
|
||||
#endif
|
||||
|
||||
#if GINT_HW_CP
|
||||
extern char gint_region_vbr;
|
||||
uint32_t VBR = (uint32_t)&gint_region_vbr - 0x100;
|
||||
#endif
|
||||
|
||||
/* Event handler entry points */
|
||||
void *inth_entry = isSH3() ? gint_inth_7705 : gint_inth_7305;
|
||||
uint32_t exch_size = (uint32_t)&gint_exch_size;
|
||||
|
@ -85,6 +88,7 @@ void kinit(void)
|
|||
/* Initialize memory allocators */
|
||||
kmalloc_init();
|
||||
|
||||
#if !GINT_HW_CP
|
||||
/* Create an allocation arena with unused static RAM */
|
||||
static kmalloc_arena_t static_ram = { 0 };
|
||||
extern uint32_t euram;
|
||||
|
@ -94,6 +98,7 @@ void kinit(void)
|
|||
static_ram.end = (void *)uram_end;
|
||||
kmalloc_init_arena(&static_ram, true);
|
||||
kmalloc_add_arena(&static_ram);
|
||||
#endif
|
||||
|
||||
/* Create an arena in the OS stack as well, for VRAM and more data */
|
||||
#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);
|
||||
|
||||
#if !GINT_OS_FX
|
||||
extern void dvram_quit(void);
|
||||
dvram_quit();
|
||||
#endif
|
||||
|
||||
gint_world_free(gint_world_os);
|
||||
gint_world_free(gint_world_addin);
|
||||
free(gint_driver_flags);
|
||||
|
|
|
@ -16,6 +16,7 @@ void __ClearKeyBuffer(void); /* ? */
|
|||
void __ConfigureStatusArea(int mode);
|
||||
void __SetQuitHandler(void (*callback)(void));
|
||||
|
||||
#if !GINT_OS_CP
|
||||
static int __osmenu_id;
|
||||
|
||||
static void __osmenu_handler(void)
|
||||
|
@ -28,6 +29,7 @@ static void __osmenu_handler(void)
|
|||
__Timer_Stop(__osmenu_id);
|
||||
__Timer_Deinstall(__osmenu_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if GINT_OS_CG
|
||||
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)
|
||||
{
|
||||
// TODO: OS menu on fx-CP
|
||||
#if !GINT_OS_CP
|
||||
__ClearKeyBuffer();
|
||||
gint_copy_vram();
|
||||
|
||||
|
@ -134,6 +138,7 @@ void gint_osmenu_native(void)
|
|||
1 /* Delay in seconds */,
|
||||
0 /* Enable return to main menu */,
|
||||
&keycode);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* gint_osmenu() - switch out of gint and call the calculator's main menu */
|
||||
|
@ -157,7 +162,11 @@ static void __handler()
|
|||
|
||||
static void __sethandler()
|
||||
{
|
||||
(void)__handler;
|
||||
// TODO: Quit handler on fx-CP
|
||||
#if !GINT_OS_CP
|
||||
__SetQuitHandler((void *)__handler);
|
||||
#endif
|
||||
}
|
||||
|
||||
void gint_set_quit_handler(gint_call_t gcall, bool do_world_switch)
|
||||
|
|
18
src/kernel/start.S
Normal file
18
src/kernel/start.S
Normal 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
|
|
@ -151,11 +151,14 @@ static int start2(int isappli, int optnum)
|
|||
|
||||
/* Load data sections and wipe the bss section. This has to be done
|
||||
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);
|
||||
|
||||
gint_load_onchip_sections();
|
||||
|
||||
#if !GINT_OS_CP
|
||||
/* 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) */
|
||||
void *rgmapped = mmu_uram();
|
||||
|
@ -167,6 +170,7 @@ static int start2(int isappli, int optnum)
|
|||
{
|
||||
fixups[i] += (uint32_t)rgmapped;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Install gint, switch VBR and initialize drivers */
|
||||
kinit();
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
.global ___GetVRAMAddress
|
||||
.global ___ConfigureStatusArea
|
||||
.global ___SetQuitHandler
|
||||
/* VRAM backup on fx-CP */
|
||||
.global ___VRAMBackup
|
||||
.global ___VRAMRestore
|
||||
|
||||
/* Reset */
|
||||
.global ___PowerOff
|
||||
|
@ -55,11 +58,18 @@
|
|||
mov.l 1f, r0 ;\
|
||||
jmp @r2 ;\
|
||||
nop ;\
|
||||
.align 4 ;\
|
||||
.balign 4 ;\
|
||||
1: .long id
|
||||
|
||||
#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
|
||||
|
||||
/* Dynamic allocation */
|
||||
|
@ -212,3 +222,26 @@ syscall_table:
|
|||
.long 0x80020070
|
||||
|
||||
#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 */
|
||||
|
|
|
@ -10,11 +10,14 @@
|
|||
#elif GINT_OS_CG
|
||||
# define SYSCALL_TABLE 0x80020070
|
||||
# define SYSCALL_TLBH 12
|
||||
#elif GINT_OS_CP
|
||||
# define NOMMU 1
|
||||
#else
|
||||
# error Unknown HW for tlbh.S!
|
||||
#endif
|
||||
|
||||
_gint_tlbh:
|
||||
#if ! NOMMU
|
||||
sts.l pr, @-r15
|
||||
stc.l gbr, @-r15
|
||||
sts.l mach, @-r15
|
||||
|
@ -50,10 +53,12 @@ map:
|
|||
lds.l @r15+, pr
|
||||
rte
|
||||
nop
|
||||
#endif
|
||||
|
||||
panic:
|
||||
/* Otherwise, panic by defaulting to the exception handler (the TLB
|
||||
miss may still be resolved by a panic handler) */
|
||||
/* Otherwise, or if there is no MMU, panic by defaulting to the
|
||||
exception handler (the TLB miss may still be resolved by a panic
|
||||
handler) */
|
||||
lds.l @r15+, macl
|
||||
lds.l @r15+, mach
|
||||
ldc.l @r15+, gbr
|
||||
|
@ -66,6 +71,7 @@ panic:
|
|||
jmp @r0
|
||||
nop
|
||||
|
||||
#if ! NOMMU
|
||||
.align 4
|
||||
|
||||
.gint:
|
||||
|
@ -80,3 +86,4 @@ panic:
|
|||
.long 0x00300000 + _srom
|
||||
.syscall:
|
||||
.long SYSCALL_TABLE
|
||||
#endif
|
||||
|
|
|
@ -244,9 +244,12 @@ void gint_copy_vram(void)
|
|||
#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);
|
||||
gint_copy_vram();
|
||||
gint_world_switch(GINT_CALL(__PowerOff, (int)show_logo));
|
||||
#endif
|
||||
}
|
||||
|
|
183
src/r61523/r61523.c
Normal file
183
src/r61523/r61523.c
Normal 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 */
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
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 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,
|
||||
dwindow.bottom - 1, color);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
#include <gint/display.h>
|
||||
#include <gint/drivers/r61523.h>
|
||||
#include <gint/drivers/r61524.h>
|
||||
#include "render-cg.h"
|
||||
#include <gint/config.h>
|
||||
#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 */
|
||||
void dupdate(void)
|
||||
{
|
||||
|
@ -19,7 +30,10 @@ void dupdate(void)
|
|||
/* Switch buffers if triple buffering is enabled */
|
||||
dvram_switch();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
__attribute__((alias("dupdate")))
|
||||
void _WEAK_dupdate(void);
|
||||
|
||||
#endif
|
||||
#endif /* GINT_RENDER_RGB */
|
||||
|
|
|
@ -1,8 +1,37 @@
|
|||
#include <gint/display.h>
|
||||
#include <gint/kmalloc.h>
|
||||
#include <gint/video.h>
|
||||
#include <gint/image.h>
|
||||
#include <gint/config.h>
|
||||
#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. */
|
||||
static uint16_t *vram_1 = NULL, *vram_2 = NULL;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
#endif
|
||||
void dvram_quit(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* OS type */
|
||||
#endif /* GINT_RENDER_RGB */
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
#include <gint/config.h>
|
||||
#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
|
||||
|
@ -39,7 +45,7 @@
|
|||
|
||||
_topti_glyph_fg_bg:
|
||||
|
||||
# Compute VRAM stride 2 * (396-width)
|
||||
# Compute VRAM stride 2 * (DWIDTH-width)
|
||||
mov.l r8, @-r15
|
||||
mov.l 1f, r8
|
||||
mov.l @(4, r15), r3
|
||||
|
@ -96,7 +102,7 @@ _topti_glyph_fg_bg:
|
|||
|
||||
_topti_glyph_fg:
|
||||
|
||||
# Compute VRAM stride 2 * (396-width)
|
||||
# Compute VRAM stride 2 * (DWIDTH-width)
|
||||
mov.l r8, @-r15
|
||||
mov.l 1f, r8
|
||||
mov.l @(4, r15), r3
|
||||
|
@ -149,7 +155,7 @@ _topti_glyph_fg:
|
|||
|
||||
_topti_glyph_bg:
|
||||
|
||||
# Compute VRAM stride 2 * (396-width)
|
||||
# Compute VRAM stride 2 * (DWIDTH-width)
|
||||
mov.l r8, @-r15
|
||||
mov.l 1f, r8
|
||||
mov.l @(4, r15), r3
|
||||
|
@ -202,6 +208,6 @@ _topti_glyph_bg:
|
|||
|
||||
.align 4
|
||||
|
||||
1: .long 396*2
|
||||
1: .long DWIDTH*2
|
||||
|
||||
#endif
|
||||
|
|
|
@ -178,6 +178,7 @@ static char const * const str_CALC[] = {
|
|||
[HWCALC_FXCG50] = "fx-CG 50/Graph 90+E",
|
||||
[HWCALC_FXCG_MANAGER] = "fx-CG Manager",
|
||||
[HWCALC_FX9860G_SLIM] = "fx-9860G Slim",
|
||||
[HWCALC_FXCP400] = "fx-CP 400",
|
||||
};
|
||||
|
||||
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 *OS_version = (void *)0x80010020;
|
||||
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 *OS_version = (void *)0x80020020;
|
||||
char const *BC_version = (void *)0x8001ffb0;
|
||||
|
|
|
@ -17,10 +17,11 @@
|
|||
|
||||
/* 0x6101: fx-9860G II, Protocol 7.00, 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( \
|
||||
u"CASIO fx-9860G family on gint", \
|
||||
u"CASIO fx-CG family on gint")
|
||||
u"CASIO fx-9860G family on gint", \
|
||||
u"CASIO fx-CG family on gint", \
|
||||
u"CASIO fx-CP family on gint")
|
||||
|
||||
static usb_dc_device_t dc_device = {
|
||||
.bLength = sizeof(usb_dc_device_t),
|
||||
|
@ -56,7 +57,8 @@ static usb_dc_string_t dc_string0 = {
|
|||
|
||||
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 */
|
||||
uint16_t serial[8];
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
#include <gint/config.h>
|
||||
|
||||
// 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 =
|
||||
GINT_HW_SWITCH(NULL, &r61524_video);
|
||||
static int current_mode_index = GINT_HW_SWITCH(-1, 0);
|
||||
GINT_HW_SWITCH(NULL, &r61524_video, &r61523_video);
|
||||
static int current_mode_index = GINT_HW_SWITCH(-1, 0, 0);
|
||||
|
||||
video_interface_t const *video_get_current_interface(void)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue