mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-28 04:23:36 +01:00
More quality review, more registers saved at startup.
This commit is contained in:
parent
a6e312a39c
commit
57a7e1c2d4
38 changed files with 673 additions and 563 deletions
34
Makefile
34
Makefile
|
@ -104,7 +104,7 @@ hdr-dep = $(wildcard include/*.h include/*/*.h)
|
|||
|
||||
|
||||
#---
|
||||
# Rule templates.
|
||||
# Rule templates
|
||||
#---
|
||||
|
||||
# C source file template:
|
||||
|
@ -129,7 +129,29 @@ endef
|
|||
|
||||
|
||||
#---
|
||||
# Building.
|
||||
# Version management
|
||||
#---
|
||||
|
||||
# Retrieve version information.
|
||||
version_string := $(shell cat version | sed 's/[-.]/ /g')
|
||||
version_type := $(word 1,$(version_string))
|
||||
version_major := $(word 2,$(version_string))
|
||||
version_minor := $(word 3,$(version_string))
|
||||
version_build := $(word 4,$(version_string))
|
||||
|
||||
# Bump build number and make up the new version integer.
|
||||
version_build := $(shell echo $$(($(version_build) + 1)))
|
||||
version_letter := $(shell echo -n $(version_type) | sed -r 's/^(.).*/\1/')
|
||||
version_symbol := $(shell printf '0x%02x%01x%01x%04x' "'$(version_letter)'" \
|
||||
$(version_major) $(version_minor) $(version_build))
|
||||
|
||||
# Tell the linker to define the version symbol.
|
||||
ldflags += -Wl,--defsym,GINT_VERSION=$(version_symbol)
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Building
|
||||
#---
|
||||
|
||||
# Generic rules
|
||||
|
@ -142,16 +164,20 @@ build:
|
|||
$(if $(VERBOSE),,@ printf '\e[35;1mdir \u00bb\e[0m mkdir $@\n')
|
||||
$(if $(VERBOSE),,@) mkdir -p $@
|
||||
|
||||
version: $(obj-std) $(obj-lib)
|
||||
@ echo '$(version_type)-$(version_major).$(version_minor)-$(version_build)' > $@
|
||||
|
||||
|
||||
$(obj-std) $(obj-lib) $(demo-obj): | build
|
||||
|
||||
$(target-std): $(obj-std)
|
||||
$(target-std): $(obj-std) version
|
||||
$(if $(VERBOSE),,@ printf '\e[35;1mlib \u00bb\e[0m ar $@\n')
|
||||
$(if $(VERBOSE),,@) $(ar) rcs $@ $(obj-std)
|
||||
@ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built libc ('
|
||||
@ printf $$(stat -c %s $@)
|
||||
@ printf ' bytes)\n\n'
|
||||
|
||||
$(target-lib): $(config) $(target-std) $(obj-lib)
|
||||
$(target-lib): $(config) $(target-std) $(obj-lib) version
|
||||
$(if $(VERBOSE),,@ printf '\e[35;1mlib \u00bb\e[0m ar $@\n')
|
||||
$(if $(VERBOSE),,@) $(ar) rcs $@ $(obj-lib)
|
||||
@ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built libgint ('
|
||||
|
|
44
TODO
44
TODO
|
@ -1,37 +1,37 @@
|
|||
Bugs to fix:
|
||||
- A few key hits ignored after leaving the application (could not reproduce)
|
||||
- Lost keyboard control at startup (could not reproduce)
|
||||
- Influence of keyboard on some timers and RTC (maybe interrupt priority)
|
||||
- Alignment of ALL .data / .rodata files is required to ensure converted data
|
||||
is properly aligned
|
||||
- Reported video ram overflow when rendering text at borderline positions
|
||||
|
||||
Simple improvements:
|
||||
- demo: Try 284x124 at (-60, -28) (all disadvantages)
|
||||
- display: Rectangle-based drawing functions
|
||||
- time: Compute CLOCKS_PER_SEC
|
||||
- string: Use cmp/str to implement memchr() (assembler examples)
|
||||
- string: Do some tests for memcmp()
|
||||
- core: Register more interrupts (and understand their parameters)
|
||||
- project: Clean headers that have some internal definitions
|
||||
- project: Check size of all library structures
|
||||
Larger improvements:
|
||||
- errno: Introduce errno and use it more or less everywhere
|
||||
- bopti: Monochrome bitmaps blending modes
|
||||
- bopti: Handle partial transparency
|
||||
- core: Implement all callbacks and a complete user API
|
||||
* core: Better save registers
|
||||
Things to do before 1.0:
|
||||
- bopti: Test partial transparency
|
||||
* core: Allow return to menu
|
||||
- serial: Implement a driver
|
||||
- usb: Implement a driver
|
||||
- esper: Cleaner playback, synthesizing
|
||||
- clock: Handle overclock (relaunch clocks when overclocking)
|
||||
- demo: Try 284x124 at (-60, -28) (all disadvantages)
|
||||
- display: Implement rectangle-based drawing functions
|
||||
- project: Add a real build-based version system
|
||||
- project: Check size of *all* library structures
|
||||
- project: Clean headers that have some internal definitions
|
||||
- project: Unify this hellish mess of register access!
|
||||
- time: Compute CLOCKS_PER_SEC
|
||||
|
||||
Things to do later:
|
||||
- bopti: Implement blending modes for monochrome bitmaps
|
||||
- clock: Handle overclock (relaunch clocks when overclocking)
|
||||
- core: Register more interrupts (and understand their parameters)
|
||||
- core: Remove redundant code linked to environment saves
|
||||
- core: Review interrupt system (again) - this one is too slow
|
||||
- errno: Introduce errno and use it more or less everywhere
|
||||
- esper: Cleaner playback, synthesizing
|
||||
- serial: Implement a driver
|
||||
- string: Use cmp/str to implement memchr() (assembler examples)
|
||||
- string: Do some tests for memcmp() and memcpy()
|
||||
- usb: Implement a driver
|
||||
|
||||
Things to investigate:
|
||||
- Packed bit fields alignment
|
||||
- Registers that may need to be saved within setjmp()
|
||||
- Registers that may need to be saved and restored by gint
|
||||
- Optimizing core/gint.c leads to raising of an illegal slot exception when
|
||||
running the interrupt handler, although it ends on rte; lds.l @r15+, mach,
|
||||
which is totally not an illegal slot.
|
||||
- Check version registers on SH7705
|
||||
|
|
|
@ -345,8 +345,8 @@ void main_menu(int *category, int *app)
|
|||
switch(tab)
|
||||
{
|
||||
case 0:
|
||||
locate(1, 1, "Demo application");
|
||||
print(2, 3, "gint version: %5s", GINT_VERSION_STR);
|
||||
print(1, 1, "Demo application");
|
||||
// print(2, 3, "gint version: %5s", GINT_VERSION_STR);
|
||||
print(2, 4, "handler size: %5d", gint_size);
|
||||
print(2, 5, "mpu type: %7s", mpu);
|
||||
print(2, 6, "romdata: %08x", &romdata);
|
||||
|
|
|
@ -95,14 +95,10 @@ static image_t *select(image_t *current)
|
|||
8 * i, 7, 7);
|
||||
if(i == row)
|
||||
{
|
||||
print(2, 2 + i + 1, "%08x", (unsigned int)
|
||||
images[i].img);
|
||||
/*
|
||||
int width, height;
|
||||
getwh(images[i].img, &width, &height);
|
||||
print(2, 2 + i + 1, "%d\x04%d", width, height);
|
||||
locate(10, 2 + i + 1, images[i].info);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,7 +143,7 @@ void test_bopti(void)
|
|||
|
||||
while(1)
|
||||
{
|
||||
if(img && (img->format & Channel_Light))
|
||||
if(img && (img->format & channel_light))
|
||||
{
|
||||
gray_start();
|
||||
gclear();
|
||||
|
|
|
@ -14,9 +14,10 @@
|
|||
*/
|
||||
|
||||
#include <internals/rtc.h>
|
||||
#include <modules/rtc.h>
|
||||
#include <mpu.h>
|
||||
|
||||
static void draw(rtc_time_t time)
|
||||
static void draw(rtc_time_t *time)
|
||||
{
|
||||
extern image_t res_rtc_segments;
|
||||
|
||||
|
@ -30,12 +31,12 @@ static void draw(rtc_time_t time)
|
|||
int digits[6];
|
||||
int i;
|
||||
|
||||
digits[0] = time.hours / 10;
|
||||
digits[1] = time.hours % 10;
|
||||
digits[2] = time.minutes / 10;
|
||||
digits[3] = time.minutes % 10;
|
||||
digits[4] = time.seconds / 10;
|
||||
digits[5] = time.seconds % 10;
|
||||
digits[0] = time->hours / 10;
|
||||
digits[1] = time->hours % 10;
|
||||
digits[2] = time->minutes / 10;
|
||||
digits[3] = time->minutes % 10;
|
||||
digits[4] = time->seconds / 10;
|
||||
digits[5] = time->seconds % 10;
|
||||
|
||||
// Drawing digits.
|
||||
for(i = 0; i < 6; i++) dimage_part(x[i], 8, &res_rtc_segments,
|
||||
|
@ -46,17 +47,18 @@ static void draw(rtc_time_t time)
|
|||
|
||||
// This should print time.year + 1900 but for the sake of this demo we
|
||||
// have tweaked the field so that it already contains time.year + 1900.
|
||||
print(4, 6, "%s %s %02d %4d", days[time.week_day],
|
||||
months[time.month], time.month_day, time.year);
|
||||
print(4, 6, "%s %s %02d %4d", days[time->week_day],
|
||||
months[time->month], time->month_day, time->year);
|
||||
}
|
||||
|
||||
static void callback(void)
|
||||
{
|
||||
extern image_t res_opt_rtc;
|
||||
rtc_time_t time = rtc_getTime();
|
||||
rtc_time_t time;
|
||||
rtc_getTime(&time);
|
||||
|
||||
dclear();
|
||||
draw(time);
|
||||
draw(&time);
|
||||
dimage_part(0, 56, &res_opt_rtc, 0, 0, 19, 8);
|
||||
dupdate();
|
||||
}
|
||||
|
@ -128,14 +130,16 @@ static void set(void)
|
|||
{ 72, 39, 7, 9 }, { 84, 39, 7, 9 }, { 90, 39, 7, 9 },
|
||||
{ 96, 39, 7, 9 }, { 102, 39, 7, 9 },
|
||||
};
|
||||
rtc_time_t time = rtc_getTime();
|
||||
rtc_time_t time;
|
||||
int region_count = 14;
|
||||
int n = 0, slide = 0, key, leave;
|
||||
|
||||
rtc_getTime(&time);
|
||||
|
||||
while(1)
|
||||
{
|
||||
dclear();
|
||||
draw(time);
|
||||
draw(&time);
|
||||
drect(regions[n].x, regions[n].y, regions[n].x + regions[n].w
|
||||
- 1, regions[n].y + regions[n].h - 1, color_invert);
|
||||
|
||||
|
@ -157,7 +161,7 @@ static void set(void)
|
|||
slide = 0;
|
||||
if(++n == region_count)
|
||||
{
|
||||
rtc_setTime(time);
|
||||
rtc_setTime(&time);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +220,7 @@ static void set(void)
|
|||
n++;
|
||||
if(n == region_count)
|
||||
{
|
||||
rtc_setTime(time);
|
||||
rtc_setTime(&time);
|
||||
return;
|
||||
}
|
||||
slide = 0;
|
||||
|
@ -235,7 +239,7 @@ void test_rtc(void)
|
|||
{
|
||||
int key, cb_id;
|
||||
|
||||
cb_id = rtc_cb_add(RTCFreq_1Hz, callback, 0);
|
||||
cb_id = rtc_cb_add(rtc_freq_1Hz, callback, 0);
|
||||
callback();
|
||||
|
||||
while(1)
|
||||
|
@ -245,10 +249,10 @@ void test_rtc(void)
|
|||
if(key == KEY_EXIT) break;
|
||||
if(key == KEY_F1)
|
||||
{
|
||||
rtc_cb_edit(cb_id, RTCFreq_None, NULL);
|
||||
rtc_cb_edit(cb_id, rtc_freq_none, NULL);
|
||||
set();
|
||||
callback();
|
||||
rtc_cb_edit(cb_id, RTCFreq_1Hz, callback);
|
||||
rtc_cb_edit(cb_id, rtc_freq_1Hz, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ static void timing_start(void)
|
|||
timer_attach(htimer, timing_timer, NULL);
|
||||
timer_start(htimer);
|
||||
|
||||
rtc_cb_edit(cb_id, RTCFreq_64Hz, timing_rtc);
|
||||
rtc_cb_edit(cb_id, rtc_freq_64Hz, timing_rtc);
|
||||
|
||||
elapsed_timer = 0;
|
||||
elapsed_rtc = 0;
|
||||
|
@ -247,7 +247,7 @@ void test_timer(void)
|
|||
|
||||
elapsed_timer = -1;
|
||||
elapsed_rtc = -1;
|
||||
cb_id = rtc_cb_add(RTCFreq_64Hz, timing_start, 0);
|
||||
cb_id = rtc_cb_add(rtc_freq_64Hz, timing_start, 0);
|
||||
|
||||
text_configure(NULL, color_black);
|
||||
|
||||
|
|
|
@ -46,8 +46,11 @@ void dimage(int x, int y, image_t *image);
|
|||
Point (left, top) is included, but (left + width, top + height) is
|
||||
excluded.
|
||||
*/
|
||||
void dimage_part(int x, int y, image_t *img, int left, int top, int width,
|
||||
int height);
|
||||
void dimage_part(
|
||||
int x, int y,
|
||||
image_t *img,
|
||||
int left, int top, int width, int height
|
||||
);
|
||||
|
||||
/*
|
||||
gimage()
|
||||
|
@ -61,7 +64,10 @@ void gimage(int x, int y, image_t *image);
|
|||
Point (left, top) is included, but (left + width, top + height) is
|
||||
excluded.
|
||||
*/
|
||||
void gimage_part(int x, int y, image_t *image, int left, int top, int width,
|
||||
int height);
|
||||
void gimage_part(
|
||||
int x, int y,
|
||||
image_t *image,
|
||||
int left, int top, int width, int height
|
||||
);
|
||||
|
||||
#endif // _BOPTI_H
|
||||
|
|
|
@ -15,9 +15,6 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define GINT_VERSION 0x000100a3
|
||||
#define GINT_VERSION_STR "00.01"
|
||||
|
||||
//---
|
||||
// System info provided by the library
|
||||
//---
|
||||
|
|
|
@ -1,19 +1,3 @@
|
|||
//---
|
||||
//
|
||||
// gint drawing module: bopti
|
||||
//
|
||||
// bopti does every job related to display images. There is only one
|
||||
// public function, but there are lots of internal optimizations.
|
||||
//
|
||||
// Some bit-manipulation expressions may look written out of nowhere. The
|
||||
// idea is always the same: get a part of the image in an 'operator',
|
||||
// which is a 32-bit variable, shift this operator so that its bits
|
||||
// correspond to the desired position for the bitmap on the screen, and
|
||||
// edit the video-ram long entry which correspond to this position using
|
||||
// a 'mask' that indicates which bits of the operator contain information.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _INTERNALS_BOPTI_H
|
||||
#define _INTERNALS_BOPTI_H
|
||||
|
||||
|
@ -21,40 +5,45 @@
|
|||
#include <display.h>
|
||||
|
||||
/*
|
||||
enum Channel
|
||||
Determines the kind of information written into a layer. Every image is
|
||||
made of one or more channels.
|
||||
channel_t
|
||||
Indicates what operation a layer is made for. Each operation affects
|
||||
the video ram differently (setting or clearing pixels, transparency,
|
||||
etc). An image is made of several layers.
|
||||
*/
|
||||
enum Channel
|
||||
typedef enum
|
||||
{
|
||||
Channel_FullAlpha = 0x01,
|
||||
Channel_LightAlpha = 0x02,
|
||||
Channel_DarkAlpha = 0x04,
|
||||
channel_full_alpha = 0x01,
|
||||
channel_light_alpha = 0x02,
|
||||
channel_dark_alpha = 0x04,
|
||||
|
||||
Channel_Mono = 0x08,
|
||||
Channel_Light = 0x10,
|
||||
Channel_Dark = 0x20,
|
||||
};
|
||||
channel_mono = 0x08,
|
||||
channel_light = 0x10,
|
||||
channel_dark = 0x20,
|
||||
|
||||
} channel_t;
|
||||
|
||||
/*
|
||||
enum Format
|
||||
Describes the various combination of channels allowed by bopti.
|
||||
format_t
|
||||
Describes the various combination of layer channels that are allowed by
|
||||
bopti. Technically one could try other formats but they're not of much
|
||||
use (transparent gray is even totally useless).
|
||||
*/
|
||||
enum Format
|
||||
typedef enum
|
||||
{
|
||||
Format_Mono = Channel_Mono,
|
||||
Format_MonoAlpha = Format_Mono | Channel_FullAlpha,
|
||||
Format_Gray = Channel_Light | Channel_Dark,
|
||||
Format_GrayAlpha = Format_Gray | Channel_FullAlpha,
|
||||
Format_GreaterAlpha = Format_Mono | Channel_LightAlpha |
|
||||
Channel_DarkAlpha
|
||||
};
|
||||
format_mono = channel_mono,
|
||||
format_mono_alpha = format_mono | channel_full_alpha,
|
||||
format_gray = channel_light | channel_dark,
|
||||
format_gray_alpha = format_gray | channel_full_alpha,
|
||||
format_greater_alpha = format_mono | channel_light_alpha |
|
||||
channel_dark_alpha
|
||||
} format_t;
|
||||
|
||||
/*
|
||||
struct Structure
|
||||
Describes an image's structure.
|
||||
structure_t
|
||||
Basically an image's dimensions, data pointer, and a few other useful
|
||||
information such as the pitch in bytes.
|
||||
*/
|
||||
struct Structure
|
||||
typedef struct
|
||||
{
|
||||
int width, height;
|
||||
int layer_size;
|
||||
|
@ -62,26 +51,37 @@ struct Structure
|
|||
const uint8_t *data;
|
||||
int columns;
|
||||
int end_size, end_bytes;
|
||||
};
|
||||
|
||||
} structure_t;
|
||||
|
||||
/*
|
||||
struct Command
|
||||
Contains a drawing operation's parameters.
|
||||
command_t
|
||||
The parameters of a drawing operation. A pointer to such a structure is
|
||||
created by the public functions and passed down to the module's
|
||||
sub-functions during rendering.
|
||||
*/
|
||||
struct Command
|
||||
typedef struct command_t
|
||||
{
|
||||
// Channel being drawn.
|
||||
enum Channel channel;
|
||||
channel_t channel;
|
||||
// Operation used (whether bopti_op_mono() or bopti_op_gray()).
|
||||
void (*op)(int offset, uint32_t operator, struct Command *command);
|
||||
void (*op)(int offset, uint32_t operator, struct command_t *command);
|
||||
// Portion of the bitmap which is drawn. 'top' and 'bottom' refer to
|
||||
// lines where 'left' and 'right' refer to column ids.
|
||||
int left, right, top, bottom;
|
||||
// Position of the bitmap on the screen.
|
||||
int x, y;
|
||||
// Rectangle masks.
|
||||
// Rectangle masks that define the drawing area.
|
||||
uint32_t masks[4];
|
||||
};
|
||||
// Video rams being used.
|
||||
union {
|
||||
// Different names, same fate. (Kingdom Hearts II)
|
||||
uint32_t *vram;
|
||||
uint32_t *v1;
|
||||
};
|
||||
uint32_t *v2;
|
||||
|
||||
} command_t;
|
||||
|
||||
// The video ram addresses are set by the public functions and used internally
|
||||
// by the module.
|
||||
|
@ -91,7 +91,7 @@ extern uint32_t *bopti_vram, *bopti_v1, *bopti_v2;
|
|||
|
||||
|
||||
//---
|
||||
// Some bopti routines.
|
||||
// Internal bopti routines.
|
||||
//---
|
||||
|
||||
/*
|
||||
|
@ -100,11 +100,12 @@ extern uint32_t *bopti_vram, *bopti_v1, *bopti_v2;
|
|||
image information. Since neutral bits are not the same for all
|
||||
operations, a mask is used to indicate which bits should be used for
|
||||
the operation. This mask is taken for the image's rectangle masks (see
|
||||
module display for more information on rectangle masks).
|
||||
Which operation is performed is determined by the channel setting.
|
||||
the 'display' module internal header for more information on rectangle
|
||||
masks). Which operation is performed is determined by the channel
|
||||
setting of the command argument.
|
||||
*/
|
||||
void bopti_op_mono(int offset, uint32_t operator, struct Command *c);
|
||||
void bopti_op_gray(int offset, uint32_t operator, struct Command *c);
|
||||
void bopti_op_mono(int offset, uint32_t operator, command_t *c);
|
||||
void bopti_op_gray(int offset, uint32_t operator, command_t *c);
|
||||
|
||||
/*
|
||||
bopti_grid() -- general form
|
||||
|
@ -115,12 +116,11 @@ void bopti_op_gray(int offset, uint32_t operator, struct Command *c);
|
|||
The need for bopti_grid_a32() is not only linked to optimization,
|
||||
because bopti_grid() will perform a 32-bit shift when x is a multiple
|
||||
of 32, which is undefined behavior.
|
||||
bopti_grid() calls bopti_grid_32() by default.
|
||||
bopti_grid() automatically calls bopti_grid_a32() when required.
|
||||
*/
|
||||
void bopti_grid_a32(const uint32_t *layer, int columns, int height,
|
||||
struct Command *c);
|
||||
void bopti_grid(const uint32_t *layer, int columns, int height,
|
||||
struct Command *c);
|
||||
command_t *c);
|
||||
void bopti_grid(const uint32_t *layer, int columns, int height, command_t *c);
|
||||
/*
|
||||
bopti_end_get()
|
||||
Returns an operator for the end of a line, whose width is lower than 32
|
||||
|
@ -138,23 +138,25 @@ uint32_t bopti_end_get2(const unsigned char **data);
|
|||
Draws the end of a layer, which can be considered as a whole layer
|
||||
whose with is lower than 32. (Actually is it lower or equal to 16;
|
||||
otherwise it would have been a column and the end would be empty). The
|
||||
'size' arguments is in bytes.
|
||||
'size' arguments is in bytes, thus 1 or 2.
|
||||
Unlike bopti_grid_a32(), bopti_end_nover() is not called automatically
|
||||
by bopti_end().
|
||||
*/
|
||||
void bopti_end_nover(const unsigned char *end, int size, struct Command *c);
|
||||
void bopti_end(const unsigned char *end, int size, struct Command *c);
|
||||
void bopti_end_nover(const unsigned char *end, int size, command_t *c);
|
||||
void bopti_end(const unsigned char *end, int size, command_t *c);
|
||||
|
||||
/*
|
||||
bopti()
|
||||
Draws a layer in the video ram.
|
||||
Draws a layer's data in the video ram areas specified in the command
|
||||
argument.
|
||||
*/
|
||||
void bopti(const unsigned char *layer, struct Structure *s, struct Command *c);
|
||||
void bopti(const unsigned char *layer, structure_t *s, command_t *c);
|
||||
|
||||
/*
|
||||
getStructure()
|
||||
Determines the image size and data pointer.
|
||||
Determines the image size (large images have a somehow different
|
||||
structure), the data pointer and a few dimensions inside the image.
|
||||
*/
|
||||
void getStructure(image_t *img, struct Structure *structure);
|
||||
void getStructure(image_t *img, structure_t *structure);
|
||||
|
||||
#endif // _INTERNALS_BOPTI_H
|
||||
|
|
|
@ -37,7 +37,7 @@ void gint_setvbr(uint32_t vbr, void (*setup)(void));
|
|||
|
||||
|
||||
//---
|
||||
// Initialization and termination routines.
|
||||
// Initialization and termination routines, environment saves.
|
||||
//---
|
||||
|
||||
/*
|
||||
|
@ -53,29 +53,80 @@ void gint_init(void);
|
|||
*/
|
||||
void gint_quit(void);
|
||||
|
||||
#include <modules/rtc.h>
|
||||
#include <modules/timer.h>
|
||||
|
||||
/*
|
||||
environment_t
|
||||
Structure where all registers used by gint are saved by default to
|
||||
ensure that the operating system is not disturbed.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
// Interrupt controller.
|
||||
uint16_t IPR[8];
|
||||
|
||||
// Real-Time Clock.
|
||||
uint8_t RCR1, RCR2;
|
||||
|
||||
// Timer Unit.
|
||||
mod_tmu_timer_t TMU0, TMU1, TMU2;
|
||||
uint8_t TSTR;
|
||||
|
||||
// I/O ports for the keyboard driver.
|
||||
uint16_t PACR, PBCR, PMCR;
|
||||
uint8_t PADR, PBDR, PMDR;
|
||||
|
||||
} environment_7705_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Interrupt controller.
|
||||
uint16_t IPR[12];
|
||||
|
||||
// Real-Time Clock.
|
||||
uint8_t RCR1, RCR2;
|
||||
|
||||
// Timer Unit.
|
||||
mod_tmu_timer_t TMU0, TMU1, TMU2;
|
||||
uint8_t TSTR;
|
||||
|
||||
// I/O ports for the keyboard driver.
|
||||
uint16_t PMCR, PNCR, PZCR;
|
||||
uint8_t PMDR, PNDR, PZDR;
|
||||
uint8_t key;
|
||||
|
||||
} environment_7305_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
environment_7705_t env_7705;
|
||||
environment_7305_t env_7305;
|
||||
|
||||
} environment_t;
|
||||
|
||||
/*
|
||||
gint_save()
|
||||
Saves many registers into a buffer to ensure that the system is not
|
||||
upset by gint's configuration when the application ends.
|
||||
Saves many registers into an internal environment buffer.
|
||||
*/
|
||||
// void gint_save_7705(gint_save_buffer_t *buffer);
|
||||
// void gint_save_7305(gint_save_buffer_t *buffer);
|
||||
void gint_save_7705(environment_7705_t *env);
|
||||
void gint_save_7305(environment_7305_t *env);
|
||||
|
||||
/*
|
||||
gint_setup()
|
||||
Configures interrupt priorities and some parameters to allow gint to
|
||||
take control of the interrupt flow.
|
||||
gint_lock_and_setup()
|
||||
Locks all interrupts (ie. disables them by default) and sets initial
|
||||
values to all registers, allows specific interrupts, etc.
|
||||
*/
|
||||
void gint_setup_7705(void);
|
||||
void gint_setup_7305(void);
|
||||
void gint_lock_and_setup_7705(void);
|
||||
void gint_lock_and_setup_7305(void);
|
||||
|
||||
/*
|
||||
gint_restore()
|
||||
Restores the parameters saved in a save buffer to give back the
|
||||
interrupt control to the system.
|
||||
gint_restore_and_unlock()
|
||||
Restores the parameters saved in the environment buffer to give back
|
||||
the interrupt control to the system.
|
||||
*/
|
||||
// void gint_restore_7705(gint_save_buffer_t *buffer);
|
||||
// void gint_restore_7305(gint_save_buffer_t *buffer);
|
||||
void gint_restore_and_unlock_7705(environment_7705_t *env);
|
||||
void gint_restore_and_unlock_7305(environment_7305_t *env);
|
||||
|
||||
/*
|
||||
gint_reg()
|
||||
|
|
|
@ -5,11 +5,12 @@
|
|||
#include <timer.h>
|
||||
#include <clock.h>
|
||||
|
||||
// Keyboard variables.
|
||||
// Current keyboard state and keyboard interrupt flag.
|
||||
extern volatile uint8_t keyboard_state[10];
|
||||
extern volatile int interrupt_flag;
|
||||
|
||||
// Key statistics.
|
||||
// Delays (milliseconds) before repetitions, last key pressed, how many times
|
||||
// it has been repeated already, time elapsed since last repetition (ms).
|
||||
extern int repeat_first, repeat_next;
|
||||
extern int last_key, last_repeats, last_time;
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
// gint core module: mmu
|
||||
//
|
||||
// A wise application should avoid tampering with the system's
|
||||
// configuration of the MMU and the TLB. This module implicitly calls the
|
||||
// system but does nothing by itself.
|
||||
// configuration of the MMU and the TLB. This module implicitly forces the
|
||||
// system to load the required pages but does not interact with the TLB.
|
||||
//
|
||||
//---
|
||||
|
||||
|
|
|
@ -9,20 +9,21 @@
|
|||
#endif
|
||||
|
||||
/*
|
||||
struct rtc_cb
|
||||
An RTC callback.
|
||||
rtc_callback_t
|
||||
An RTC callback with a unique id.
|
||||
*/
|
||||
struct rtc_cb
|
||||
typedef struct
|
||||
{
|
||||
rtc_frequency_t freq;
|
||||
int id;
|
||||
|
||||
void (*callback)(void);
|
||||
int repeats;
|
||||
};
|
||||
|
||||
} rtc_callback_t;
|
||||
|
||||
// The callback array.
|
||||
struct rtc_cb cb_array[RTC_CB_ARRAY_SIZE];
|
||||
rtc_callback_t cb_array[RTC_CB_ARRAY_SIZE];
|
||||
|
||||
/*
|
||||
rtc_perodic_interrupt()
|
||||
|
@ -37,118 +38,4 @@ void rtc_periodic_interrupt(void);
|
|||
*/
|
||||
void rtc_cb_interrupt(void);
|
||||
|
||||
/*
|
||||
struct mod_rtc
|
||||
This structure describes the arrangement of RTC register in the memory.
|
||||
Curious thing, on SH7705, registers RYRAR and RCR3 are at a completely
|
||||
different address than the other ones. This module does not use these
|
||||
registers, so they were not included in the structure.
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct mod_rtc
|
||||
{
|
||||
unsigned char const R64CNT;
|
||||
unsigned char _1;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :1;
|
||||
unsigned TENS :3;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RSECCNT;
|
||||
unsigned char _2;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :1;
|
||||
unsigned TENS :3;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RMINCNT;
|
||||
unsigned char _3;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :2;
|
||||
unsigned TENS :2;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RHRCNT;
|
||||
unsigned char _4;
|
||||
|
||||
// 0 = Sunday, 1 = Monday, ..., 6 = Saturday, 7 = prohibited setting.
|
||||
unsigned char RWKCNT;
|
||||
unsigned char _5;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :2;
|
||||
unsigned TENS :2;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RDAYCNT;
|
||||
unsigned char _6;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :3;
|
||||
unsigned TENS :1;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RMONCNT;
|
||||
unsigned char _7;
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned THOUSANDS :4;
|
||||
unsigned HUNDREDS :4;
|
||||
unsigned TENS :4;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RYRCNT;
|
||||
unsigned char _8[12];
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned CF :1;
|
||||
unsigned :2;
|
||||
unsigned CIE :1;
|
||||
unsigned AIE :1;
|
||||
unsigned :2;
|
||||
unsigned AF :1;
|
||||
};
|
||||
} RCR1;
|
||||
unsigned char _9;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned PEF :1;
|
||||
unsigned PES :3;
|
||||
unsigned :1;
|
||||
unsigned ADJ :1;
|
||||
unsigned RESET :1;
|
||||
unsigned START :1;
|
||||
};
|
||||
} RCR2;
|
||||
} __attribute__((packed));
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/*
|
||||
We don't need to access the registers in a complicated way like the
|
||||
function of the timer module. Let's make it simple.
|
||||
*/
|
||||
#define RTC_SH7705 ((volatile struct mod_rtc *)0xfffffec0)
|
||||
#define RTC_SH7305 ((volatile struct mod_rtc *)0xa413fec0)
|
||||
|
||||
#endif // _INTERNALS_RTC_H
|
||||
|
|
|
@ -3,6 +3,15 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
// Padding is just empty space, we don't want to give it a name. There's also
|
||||
// some subtle preprocessor trick to automatically add a (supposedly) unique
|
||||
// name to each padding member. For instance the substitution may operate as:
|
||||
// name(__LINE__) -> namesub(78) -> _##78 -> _78
|
||||
#define namesub(x) _##x
|
||||
#define name(x) namesub(x)
|
||||
#define pad(bytes) \
|
||||
uint8_t name(__LINE__)[bytes] \
|
||||
|
||||
// Fixed-width types for bit field are totally meaningless.
|
||||
typedef unsigned uint;
|
||||
|
||||
|
|
131
include/modules/rtc.h
Normal file
131
include/modules/rtc.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
#ifndef _MODULES_RTC_H
|
||||
#define _MODULES_RTC_H
|
||||
|
||||
#include <modules/macros.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
mod_rtc_rcr1_t
|
||||
First RTC configuration register.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
byte_union(,
|
||||
uint CF :1; /* Carry flag */
|
||||
uint :2;
|
||||
uint CIE :1; /* Carry interrupt enable */
|
||||
uint AIE :1; /* Alarm interrupt enable */
|
||||
uint :2;
|
||||
uint AF :1; /* Alarm flag */
|
||||
);
|
||||
|
||||
} __attribute__((packed)) mod_rtc_rcr1_t;
|
||||
|
||||
/*
|
||||
mod_rtc_rcr2_t
|
||||
Second RTC configuration register.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
byte_union(,
|
||||
uint PEF :1; /* Periodic interrupt flag */
|
||||
uint PES :3; /* Periodic interrupt interval */
|
||||
uint :1;
|
||||
uint ADJ :1; /* 30-second adjustment */
|
||||
uint RESET :1; /* Reset */
|
||||
uint START :1; /* Start bit */
|
||||
);
|
||||
|
||||
} __attribute__((packed)) mod_rtc_rcr2_t;
|
||||
|
||||
/*
|
||||
mod_rtc_rcr3_t
|
||||
Third RTC configuration register.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte_union(,
|
||||
uint YAEN :1;
|
||||
uint :7;
|
||||
);
|
||||
|
||||
} __attribute__((packed)) mod_rtc_rcr3_t;
|
||||
*/
|
||||
|
||||
/*
|
||||
mod_rtc_time_t
|
||||
A set of registers describing the current time in BCD format.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const uint8_t R64CNT; /* More or less a 64-Hz counter */
|
||||
pad(1);
|
||||
|
||||
byte_union(RSECCNT, /* Second count */
|
||||
uint :1;
|
||||
uint TENS :3;
|
||||
uint ONES :4;
|
||||
);
|
||||
pad(1);
|
||||
|
||||
byte_union(RMINCNT, /* Minute count */
|
||||
uint :1;
|
||||
uint TENS :3;
|
||||
uint ONES :4;
|
||||
);
|
||||
pad(1);
|
||||
|
||||
byte_union(RHRCNT, /* Hour count */
|
||||
uint :2;
|
||||
uint TENS :2;
|
||||
uint ONES :4;
|
||||
);
|
||||
pad(1);
|
||||
|
||||
/* 0 = Sunday .. 6 = Saturday, other settings are prohibited. */
|
||||
uint8_t RWKCNT; /* Day of week */
|
||||
pad(1);
|
||||
|
||||
byte_union(RDAYCNT, /* Day count */
|
||||
uint :2;
|
||||
uint TENS :2;
|
||||
uint ONES :4;
|
||||
);
|
||||
pad(1);
|
||||
|
||||
byte_union(RMONCNT, /* Month count */
|
||||
uint :3;
|
||||
uint TENS :1;
|
||||
uint ONES :4;
|
||||
);
|
||||
pad(1);
|
||||
|
||||
word_union(RYRCNT, /* Year count */
|
||||
uint THOUSANDS :4;
|
||||
uint HUNDREDS :4;
|
||||
uint TENS :4;
|
||||
uint ONES :4;
|
||||
);
|
||||
|
||||
} __attribute__((packed, aligned(2))) mod_rtc_time_t;
|
||||
|
||||
/*
|
||||
mod_rtc_t (resides into gint memory)
|
||||
Three control registers and timer information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/* RCR1, RCR2, and RCR3 are the same for both platforms. */
|
||||
volatile mod_rtc_rcr1_t *RCR1;
|
||||
volatile mod_rtc_rcr2_t *RCR2;
|
||||
// volatile mod_rtc_rcr3_t *RCR3;
|
||||
/* Current time in register memory */
|
||||
volatile mod_rtc_time_t *time;
|
||||
|
||||
} mod_rtc_t;
|
||||
|
||||
// All you need to use is this structure, initialized by gint, which contains
|
||||
// address that work with your execution platform.
|
||||
extern mod_rtc_t RTC;
|
||||
|
||||
#endif // _INTERNALS_RTC_H
|
|
@ -59,6 +59,6 @@ typedef struct
|
|||
|
||||
// The actual thing is there. It's initialized by gint at startup and contains
|
||||
// addresses and information suitable for the current platform.
|
||||
extern volatile mod_tmu_t TMU;
|
||||
extern mod_tmu_t TMU;
|
||||
|
||||
#endif // _MODULES_TIMER
|
||||
|
|
|
@ -49,7 +49,7 @@ typedef enum
|
|||
|
||||
// Global MPU variable, accessible for direct tests. Initialized at the
|
||||
// beginning of execution.
|
||||
extern mpu_t MPU_CURRENT;
|
||||
extern const mpu_t MPU_CURRENT;
|
||||
|
||||
// Quick SH3 test. It is safer to assume that an unknown model is SH4 because
|
||||
// SH3-based models are not produced anymore.
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
//
|
||||
// gint core module: rtc
|
||||
//
|
||||
// Manages RTC. This module is used behind standard module time.
|
||||
// Manages the Real-Time Clock (RTC). This module provides access to the
|
||||
// current time as well as regular callbacks at predefined frequencies,
|
||||
// more or less like a timer.
|
||||
// The standard time module is built upon this one.
|
||||
//
|
||||
//---
|
||||
|
||||
|
@ -36,14 +39,14 @@ typedef struct
|
|||
Reads the current time from the RTC. There is no guarantee that the
|
||||
week day is correct (use the time API for that).
|
||||
*/
|
||||
rtc_time_t rtc_getTime(void);
|
||||
void rtc_getTime(rtc_time_t *time);
|
||||
|
||||
/*
|
||||
rtc_setTime()
|
||||
Sets the time in the RTC registers. The week day is set to 0 if greater
|
||||
than 6. Other fields are not checked.
|
||||
*/
|
||||
void rtc_setTime(rtc_time_t time);
|
||||
void rtc_setTime(const rtc_time_t *time);
|
||||
|
||||
|
||||
|
||||
|
@ -58,14 +61,14 @@ void rtc_setTime(rtc_time_t time);
|
|||
*/
|
||||
typedef enum
|
||||
{
|
||||
RTCFreq_500mHz = 7,
|
||||
RTCFreq_1Hz = 6,
|
||||
RTCFreq_2Hz = 5,
|
||||
RTCFreq_4Hz = 4,
|
||||
RTCFreq_16Hz = 3,
|
||||
RTCFreq_64Hz = 2,
|
||||
RTCFreq_256Hz = 1,
|
||||
RTCFreq_None = 0,
|
||||
rtc_freq_500mHz = 7,
|
||||
rtc_freq_1Hz = 6,
|
||||
rtc_freq_2Hz = 5,
|
||||
rtc_freq_4Hz = 4,
|
||||
rtc_freq_16Hz = 3,
|
||||
rtc_freq_64Hz = 2,
|
||||
rtc_freq_256Hz = 1,
|
||||
rtc_freq_none = 0,
|
||||
|
||||
} rtc_frequency_t;
|
||||
|
||||
|
@ -94,7 +97,7 @@ void rtc_cb_end(int id);
|
|||
-1 Callback does not exist
|
||||
-2 Invalid parameters
|
||||
This function never removes a callback. Call rtc_cb_end() for this. One
|
||||
can set the function to NULL or the frequency to RTCFreq_None to
|
||||
can set the function to NULL or the frequency to rtc_freq_none to
|
||||
temporarily disable the callback.
|
||||
*/
|
||||
int rtc_cb_edit(int id, rtc_frequency_t new_freq, void (*new_function)(void));
|
||||
|
|
|
@ -12,17 +12,17 @@ uint32_t *bopti_vram, *bopti_v1, *bopti_v2;
|
|||
module display for more information on rectangle masks).
|
||||
Which operation is performed is determined by the channel setting.
|
||||
*/
|
||||
void bopti_op_mono(int offset, uint32_t operator, struct Command *c)
|
||||
void bopti_op_mono(int offset, uint32_t operator, command_t *c)
|
||||
{
|
||||
operator &= c->masks[offset & 3];
|
||||
|
||||
switch(c->channel)
|
||||
{
|
||||
case Channel_FullAlpha:
|
||||
case channel_full_alpha:
|
||||
bopti_vram[offset] &= ~operator;
|
||||
break;
|
||||
|
||||
case Channel_Mono:
|
||||
case channel_mono:
|
||||
bopti_vram[offset] |= operator;
|
||||
break;
|
||||
|
||||
|
@ -30,31 +30,31 @@ void bopti_op_mono(int offset, uint32_t operator, struct Command *c)
|
|||
break;
|
||||
}
|
||||
}
|
||||
void bopti_op_gray(int offset, uint32_t operator, struct Command *c)
|
||||
void bopti_op_gray(int offset, uint32_t operator, command_t *c)
|
||||
{
|
||||
operator &= c->masks[offset & 3];
|
||||
|
||||
switch(c->channel)
|
||||
{
|
||||
case Channel_FullAlpha:
|
||||
case channel_full_alpha:
|
||||
bopti_v1[offset] &= ~operator;
|
||||
bopti_v2[offset] &= ~operator;
|
||||
break;
|
||||
|
||||
case Channel_LightAlpha:
|
||||
case Channel_DarkAlpha:
|
||||
case channel_light_alpha:
|
||||
case channel_dark_alpha:
|
||||
break;
|
||||
|
||||
case Channel_Mono:
|
||||
case channel_mono:
|
||||
bopti_v1[offset] |= operator;
|
||||
bopti_v2[offset] |= operator;
|
||||
break;
|
||||
|
||||
case Channel_Light:
|
||||
case channel_light:
|
||||
bopti_v1[offset] |= operator;
|
||||
break;
|
||||
|
||||
case Channel_Dark:
|
||||
case channel_dark:
|
||||
bopti_v2[offset] |= operator;
|
||||
break;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ void bopti_op_gray(int offset, uint32_t operator, struct Command *c)
|
|||
of 32, which is undefined behavior.
|
||||
*/
|
||||
void bopti_grid_a32(const uint32_t *layer, int column_count, int height,
|
||||
struct Command *c)
|
||||
command_t *c)
|
||||
{
|
||||
int vram_column_offset = (c->y << 2) + (c->x >> 5);
|
||||
int vram_offset = vram_column_offset;
|
||||
|
@ -91,7 +91,7 @@ void bopti_grid_a32(const uint32_t *layer, int column_count, int height,
|
|||
}
|
||||
}
|
||||
void bopti_grid(const uint32_t *layer, int column_count, int height,
|
||||
struct Command *c)
|
||||
command_t *c)
|
||||
{
|
||||
if(!column_count) return;
|
||||
if(!(c->x & 31))
|
||||
|
@ -177,9 +177,9 @@ uint32_t bopti_end_get2(const unsigned char **data)
|
|||
|
||||
Draws the end of a layer, which can be considered as a whole layer
|
||||
whose with is lower than 32. (Actually is it lower or equal to 16;
|
||||
otherwise it would have been a column and the end would be empty).
|
||||
otherwise it would have been a column and the end would be empty.)
|
||||
*/
|
||||
void bopti_end_nover(const unsigned char *end, int size, struct Command *c)
|
||||
void bopti_end_nover(const unsigned char *end, int size, command_t *c)
|
||||
{
|
||||
uint32_t (*get)(const unsigned char **data) =
|
||||
(size == 2) ? bopti_end_get2 : bopti_end_get1;
|
||||
|
@ -199,19 +199,17 @@ void bopti_end_nover(const unsigned char *end, int size, struct Command *c)
|
|||
{
|
||||
operator = (*get)(&end);
|
||||
operator <<= shift;
|
||||
|
||||
(c->op)(vram_offset, operator, c);
|
||||
|
||||
(c->op)(vram_offset, operator, c);
|
||||
vram_offset += 4;
|
||||
}
|
||||
}
|
||||
void bopti_end(const unsigned char *end, int size, struct Command *c)
|
||||
void bopti_end(const unsigned char *end, int size, command_t *c)
|
||||
{
|
||||
uint32_t (*get)(const unsigned char **data) =
|
||||
(size == 2) ? (bopti_end_get2) : (bopti_end_get1);
|
||||
|
||||
int vram_offset = (c->y << 2) + (c->x >> 5);
|
||||
uint32_t row_data, operator;
|
||||
uint32_t row_data;
|
||||
int row;
|
||||
|
||||
int shift_base = (32 - (size << 3));
|
||||
|
@ -225,15 +223,8 @@ void bopti_end(const unsigned char *end, int size, struct Command *c)
|
|||
for(row = c->top; row < c->bottom; row++)
|
||||
{
|
||||
row_data = (*get)(&end);
|
||||
|
||||
operator = row_data >> shift1;
|
||||
(c->op)(vram_offset, operator, c);
|
||||
|
||||
|
||||
operator = row_data << shift2;
|
||||
(c->op)(vram_offset + 1, operator, c);
|
||||
|
||||
|
||||
(c->op)(vram_offset, row_data >> shift1, c);
|
||||
(c->op)(vram_offset + 1, row_data << shift2, c);
|
||||
vram_offset += 4;
|
||||
}
|
||||
}
|
||||
|
@ -248,7 +239,7 @@ void bopti_end(const unsigned char *end, int size, struct Command *c)
|
|||
bopti()
|
||||
Draws a layer in the video ram.
|
||||
*/
|
||||
void bopti(const unsigned char *layer, struct Structure *s, struct Command *c)
|
||||
void bopti(const unsigned char *layer, structure_t *s, command_t *c)
|
||||
{
|
||||
const unsigned char *grid, *end;
|
||||
int grid_columns, has_end;
|
||||
|
@ -283,9 +274,10 @@ void bopti(const unsigned char *layer, struct Structure *s, struct Command *c)
|
|||
|
||||
/*
|
||||
getStructure()
|
||||
Determines the image size and data pointer.
|
||||
Determines the image size (large images have a somehow different
|
||||
structure), the data pointer and a few dimensions inside the image.
|
||||
*/
|
||||
void getStructure(image_t *img, struct Structure *s)
|
||||
void getStructure(image_t *img, structure_t *s)
|
||||
{
|
||||
int column_count, end, end_bytes, layer;
|
||||
|
||||
|
|
|
@ -12,12 +12,12 @@ void dimage_part(int x, int y, image_t *img, int left, int top, int width,
|
|||
{
|
||||
if(!img || img->magic != 0x01) return;
|
||||
|
||||
struct Structure s;
|
||||
struct Command command;
|
||||
structure_t s;
|
||||
command_t command;
|
||||
int actual_width;
|
||||
int format = img->format, i = 0;
|
||||
|
||||
if(format != Format_Mono && format != Format_MonoAlpha) return;
|
||||
if(format != format_mono && format != format_mono_alpha) return;
|
||||
getStructure(img, &s);
|
||||
if(width < 0) width = s.width;
|
||||
if(height < 0) height = s.height;
|
||||
|
|
|
@ -13,8 +13,8 @@ void gimage_part(int x, int y, image_t *img, int left, int top, int width,
|
|||
{
|
||||
if(!img || img->magic != 0x01) return;
|
||||
|
||||
struct Structure s;
|
||||
struct Command command;
|
||||
structure_t s;
|
||||
command_t command;
|
||||
int actual_width;
|
||||
int format = img->format, i = 0;
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ void clock_measure(void)
|
|||
{
|
||||
htimer_7705 = htimer_setup(timer_user, 0xffffffff, timer_Po_4,
|
||||
1);
|
||||
cb_id_7705 = rtc_cb_add(RTCFreq_256Hz, clock_measure_7705, 0);
|
||||
cb_id_7705 = rtc_cb_add(rtc_freq_256Hz, clock_measure_7705, 0);
|
||||
}
|
||||
|
||||
// On SH7305, assuming clock mode 3, we can compute the clock
|
||||
|
@ -268,5 +268,5 @@ static void clock_measure_7705_callback(void)
|
|||
static void clock_measure_7705(void)
|
||||
{
|
||||
timer_start(htimer_7705);
|
||||
rtc_cb_edit(cb_id_7705, RTCFreq_256Hz, clock_measure_7705_callback);
|
||||
rtc_cb_edit(cb_id_7705, rtc_freq_256Hz, clock_measure_7705_callback);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ extern uint32_t
|
|||
etext, btext, // Location of .text section
|
||||
bdata, edata, // Location of .data section
|
||||
bbss, ebss, // Location of .bss section
|
||||
bgint, egint, // Location of interrut handler and gint data
|
||||
bgint, egint, // Location of interrupt handler and gint data
|
||||
gint_vbr, // VBR address
|
||||
romdata; // ROM address of .data section contents
|
||||
|
||||
|
@ -45,7 +45,7 @@ __attribute__((section(".pretext.entry"))) int start(void)
|
|||
{
|
||||
#ifdef GINT_DIAGNOSTICS
|
||||
|
||||
// Ok, so fill as much information as possible so that in case anything
|
||||
// OK, so fill as much information as possible so that in case anything
|
||||
// goes wrong we can try to analyze what's been going on.
|
||||
volatile gint_diagnostics_t *dg = gint_diagnostics();
|
||||
|
||||
|
@ -77,7 +77,7 @@ __attribute__((section(".pretext.entry"))) int start(void)
|
|||
dg->section_data.length = (uint32_t)&edata - (uint32_t)&bdata;
|
||||
dg->section_bss.address = (uint32_t)&bbss;
|
||||
dg->section_bss.length = (uint32_t)&ebss - (uint32_t)&bbss;
|
||||
dg->romdata = (uint32_t)&romdata;
|
||||
dg->romdata = (uint32_t)&romdata;
|
||||
|
||||
// Basic information about the running library.
|
||||
dg->vbr_address = (uint32_t)&gint_vbr;
|
||||
|
@ -108,10 +108,11 @@ __attribute__((section(".pretext.entry"))) int start(void)
|
|||
dg->stage = stage_mmu;
|
||||
#endif
|
||||
|
||||
// Detecting the MPU type, initializing the register module addresses,
|
||||
// and initializing gint.
|
||||
mpu_init();
|
||||
mod_init();
|
||||
// Initializing gint, which does several things:
|
||||
// - Detect the MPU and platform
|
||||
// - Initialize register addresses in a platform-independent way
|
||||
// - Save the current environment information in a large buffer
|
||||
// - Set up the interrupt handler and configure everything gint needs
|
||||
gint_init();
|
||||
|
||||
#ifdef GINT_DIAGNOSTICS
|
||||
|
@ -148,16 +149,15 @@ __attribute__((section(".pretext.entry"))) int start(void)
|
|||
if(!x) exit_code = main();
|
||||
|
||||
|
||||
|
||||
#ifdef GINT_DIAGNOSTICS
|
||||
dg->stage = stage_leaving;
|
||||
#endif
|
||||
|
||||
/* TODO Flush and close opened streams. */
|
||||
|
||||
// Calling exit handlers.
|
||||
// Calling exit handlers and destructors.
|
||||
while(atexit_index > 0) (*atexit_handlers[--atexit_index])();
|
||||
|
||||
// Calling the destructors.
|
||||
fini();
|
||||
|
||||
#ifdef GINT_DIAGNOSTICS
|
||||
|
|
|
@ -33,8 +33,8 @@ static void show_error(const char *name, uint32_t *access_mode, uint32_t *tea,
|
|||
{
|
||||
uint32_t *vram = display_getCurrentVRAM();
|
||||
uint32_t spc, ssr;
|
||||
__asm__("stc spc, %0" : "=rm"(spc));
|
||||
__asm__("stc ssr, %0" : "=rm"(ssr));
|
||||
__asm__("stc spc, %0" : "=r"(spc));
|
||||
__asm__("stc ssr, %0" : "=r"(ssr));
|
||||
|
||||
dclear();
|
||||
text_configure(NULL, color_black);
|
||||
|
|
|
@ -1,12 +1,3 @@
|
|||
//---
|
||||
//
|
||||
// gint core module: interrupt handler
|
||||
//
|
||||
// Central point of the library. Controls the interrupt handler and
|
||||
// defines a few functions to configure callbacks for some interrupts.
|
||||
//
|
||||
//---
|
||||
|
||||
#include <internals/gint.h>
|
||||
#include <internals/interrupt_maps.h>
|
||||
#include <internals/exceptions.h>
|
||||
|
@ -110,10 +101,10 @@ void gint_invoke(uint8_t type, uint8_t subtype)
|
|||
uint16_t *pc;
|
||||
|
||||
// Getting some initial information to work with.
|
||||
__asm__("stc spc, %0" : "=rm"(pc));
|
||||
__asm__("stc spc, %0" : "=r"(pc));
|
||||
tea = gint_reg(register_tea);
|
||||
tra = gint_reg(register_tra);
|
||||
tcpr_2 = (void *)0xfffffeb8;
|
||||
tcpr_2 = (void *)0xfffffeb8; /* SH7705 only */
|
||||
|
||||
// Building up the argument list.
|
||||
for(int i = 0; i < 3; i++) switch(gint_handlers[type].args[i])
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
//---
|
||||
//
|
||||
// gint core module: sh7305 interrupt handler
|
||||
//
|
||||
// Of course all the work related to interrupts is heavily platform-
|
||||
// dependent. This module handles interrupts and configures the MPU to
|
||||
// save and restore the system's configuration when execution ends.
|
||||
//
|
||||
//---
|
||||
|
||||
#include <internals/gint.h>
|
||||
#include <internals/rtc.h>
|
||||
#include <modules/timer.h>
|
||||
#include <modules/rtc.h>
|
||||
#include <gint.h>
|
||||
#include <timer.h>
|
||||
#include <7305.h>
|
||||
|
@ -38,108 +29,108 @@ volatile void *gint_reg_7305(gint_register_t reg)
|
|||
|
||||
|
||||
//---
|
||||
// Setup.
|
||||
// Register saves, setup, interrupt locks, register restoration.
|
||||
//---
|
||||
|
||||
static unsigned short ipr[12];
|
||||
static unsigned char rcr2;
|
||||
// Saves of the keyboard registers. Could be better.
|
||||
static unsigned short inj1, inj2, det;
|
||||
static unsigned char data1, data2, keys, reg;
|
||||
|
||||
static void gint_priority_lock_7305(void)
|
||||
void gint_save_7305(environment_7305_t *e)
|
||||
{
|
||||
// Saving the current interrupt priorities.
|
||||
ipr[0] = INTX.IPRA.WORD;
|
||||
ipr[1] = INTX.IPRB.WORD;
|
||||
ipr[2] = INTX.IPRC.WORD;
|
||||
ipr[3] = INTX.IPRD.WORD;
|
||||
ipr[4] = INTX.IPRE.WORD;
|
||||
ipr[5] = INTX.IPRF.WORD;
|
||||
ipr[6] = INTX.IPRG.WORD;
|
||||
ipr[7] = INTX.IPRH.WORD;
|
||||
ipr[8] = INTX.IPRI.WORD;
|
||||
ipr[9] = INTX.IPRJ.WORD;
|
||||
ipr[10] = INTX.IPRK.WORD;
|
||||
ipr[11] = INTX.IPRL.WORD;
|
||||
// Saving interrupt priorities.
|
||||
e->IPR[0] = INTX.IPRA.WORD;
|
||||
e->IPR[1] = INTX.IPRB.WORD;
|
||||
e->IPR[2] = INTX.IPRC.WORD;
|
||||
e->IPR[3] = INTX.IPRD.WORD;
|
||||
e->IPR[4] = INTX.IPRE.WORD;
|
||||
e->IPR[5] = INTX.IPRF.WORD;
|
||||
e->IPR[6] = INTX.IPRG.WORD;
|
||||
e->IPR[7] = INTX.IPRH.WORD;
|
||||
e->IPR[8] = INTX.IPRI.WORD;
|
||||
e->IPR[9] = INTX.IPRJ.WORD;
|
||||
e->IPR[10] = INTX.IPRK.WORD;
|
||||
e->IPR[11] = INTX.IPRL.WORD;
|
||||
|
||||
// Saving RTC registers.
|
||||
e->RCR1 = RTC.RCR1->byte;
|
||||
e->RCR2 = RTC.RCR2->byte;
|
||||
|
||||
// Saving TMU registers.
|
||||
e->TMU0 = *(TMU.timers[0]);
|
||||
e->TMU1 = *(TMU.timers[1]);
|
||||
e->TMU2 = *(TMU.timers[2]);
|
||||
e->TSTR = TMU.TSTR->byte;
|
||||
|
||||
// Saving port data used to access the keyboard.
|
||||
e->PMCR = *((volatile uint16_t *)0xa4050116);
|
||||
e->PMDR = *((volatile uint8_t *)0xa4050136);
|
||||
e->PNCR = *((volatile uint16_t *)0xa4050118);
|
||||
e->PNDR = *((volatile uint8_t *)0xa4050138);
|
||||
e->PZCR = *((volatile uint16_t *)0xa405014c);
|
||||
e->PZDR = *((volatile uint8_t *)0xa405016c);
|
||||
e->key = *((volatile uint8_t *)0xa40501c6);
|
||||
}
|
||||
|
||||
void gint_lock_and_setup_7305(void)
|
||||
{
|
||||
// Disabling everything by default to avoid freezing on non-handled
|
||||
// interrupts.
|
||||
INTX.IPRA.WORD = 0x0000;
|
||||
INTX.IPRB.WORD = 0x0000;
|
||||
INTX.IPRC.WORD = 0x0000;
|
||||
INTX.IPRD.WORD = 0x0000;
|
||||
INTX.IPRE.WORD = 0x0000;
|
||||
INTX.IPRF.WORD = 0x0000;
|
||||
INTX.IPRG.WORD = 0x0000;
|
||||
INTX.IPRH.WORD = 0x0000;
|
||||
INTX.IPRI.WORD = 0x0000;
|
||||
INTX.IPRJ.WORD = 0x0000;
|
||||
INTX.IPRK.WORD = 0x0000;
|
||||
INTX.IPRL.WORD = 0x0000;
|
||||
INTX.IPRA.WORD = 0x0000;
|
||||
INTX.IPRB.WORD = 0x0000;
|
||||
INTX.IPRC.WORD = 0x0000;
|
||||
INTX.IPRD.WORD = 0x0000;
|
||||
INTX.IPRE.WORD = 0x0000;
|
||||
INTX.IPRF.WORD = 0x0000;
|
||||
INTX.IPRG.WORD = 0x0000;
|
||||
INTX.IPRH.WORD = 0x0000;
|
||||
INTX.IPRI.WORD = 0x0000;
|
||||
INTX.IPRJ.WORD = 0x0000;
|
||||
INTX.IPRK.WORD = 0x0000;
|
||||
INTX.IPRL.WORD = 0x0000;
|
||||
|
||||
// Saving keyboard registers.
|
||||
inj1 = *((volatile unsigned short *)0xa4050116);
|
||||
data1 = *((volatile unsigned char *)0xa4050136);
|
||||
inj2 = *((volatile unsigned short *)0xa4050118);
|
||||
data2 = *((volatile unsigned char *)0xa4050138);
|
||||
det = *((volatile unsigned short *)0xa405014c);
|
||||
keys = *((volatile unsigned char *)0xa405016c);
|
||||
reg = *((volatile unsigned char *)0xa40501c6);
|
||||
|
||||
// Allowing RTC. Keyboard analysis is done regularly using a RTC
|
||||
// because SH7305's special KEYSC interface does not allow us to clear
|
||||
// the keyboard interrupt flags.
|
||||
// Allowing RTC and timer to schedule automatic tasks such as keyboard
|
||||
// analysis.
|
||||
INTX.IPRK._RTC = 10;
|
||||
INTX.IPRA.TMU0_0 = 12;
|
||||
INTX.IPRA.TMU0_1 = 12;
|
||||
INTX.IPRA.TMU0_2 = 12;
|
||||
|
||||
// Don't enable the RTC interrupt by default.
|
||||
RTC.RCR2->byte = 0x09;
|
||||
}
|
||||
|
||||
static void gint_priority_unlock_7305(void)
|
||||
void gint_restore_and_unlock_7305(environment_7305_t *e)
|
||||
{
|
||||
// Restoring the interrupt priorities.
|
||||
INTX.IPRA.WORD = ipr[0];
|
||||
INTX.IPRB.WORD = ipr[1];
|
||||
INTX.IPRC.WORD = ipr[2];
|
||||
INTX.IPRD.WORD = ipr[3];
|
||||
INTX.IPRE.WORD = ipr[4];
|
||||
INTX.IPRF.WORD = ipr[5];
|
||||
INTX.IPRG.WORD = ipr[6];
|
||||
INTX.IPRH.WORD = ipr[7];
|
||||
INTX.IPRI.WORD = ipr[8];
|
||||
INTX.IPRJ.WORD = ipr[9];
|
||||
INTX.IPRK.WORD = ipr[10];
|
||||
INTX.IPRL.WORD = ipr[11];
|
||||
INTX.IPRA.WORD = e->IPR[0];
|
||||
INTX.IPRB.WORD = e->IPR[1];
|
||||
INTX.IPRC.WORD = e->IPR[2];
|
||||
INTX.IPRD.WORD = e->IPR[3];
|
||||
INTX.IPRE.WORD = e->IPR[4];
|
||||
INTX.IPRF.WORD = e->IPR[5];
|
||||
INTX.IPRG.WORD = e->IPR[6];
|
||||
INTX.IPRH.WORD = e->IPR[7];
|
||||
INTX.IPRI.WORD = e->IPR[8];
|
||||
INTX.IPRJ.WORD = e->IPR[9];
|
||||
INTX.IPRK.WORD = e->IPR[10];
|
||||
INTX.IPRL.WORD = e->IPR[11];
|
||||
|
||||
// Restoring keyboard registers.
|
||||
*((volatile unsigned short *)0xa4050116) = inj1;
|
||||
*((volatile unsigned char *)0xa4050136) = data1;
|
||||
*((volatile unsigned short *)0xa4050118) = inj2;
|
||||
*((volatile unsigned char *)0xa4050138) = data2;
|
||||
*((volatile unsigned short *)0xa405014c) = det;
|
||||
*((volatile unsigned char *)0xa405016c) = keys;
|
||||
*((volatile unsigned char *)0xa40501c6) = reg;
|
||||
}
|
||||
|
||||
void gint_setup_7305(void)
|
||||
{
|
||||
volatile struct mod_rtc *RTC = RTC_SH7305;
|
||||
|
||||
gint_priority_lock_7305();
|
||||
|
||||
// Saving the RTC configuration.
|
||||
rcr2 = RTC->RCR2.BYTE;
|
||||
// Disabling RTC interrupts by default.
|
||||
RTC->RCR2.BYTE = 0x09;
|
||||
}
|
||||
|
||||
void gint_stop_7305(void)
|
||||
{
|
||||
volatile struct mod_rtc *RTC = RTC_SH7305;
|
||||
|
||||
gint_priority_unlock_7305();
|
||||
|
||||
// Restoring the RTC configuration.
|
||||
RTC->RCR2.BYTE = rcr2;
|
||||
// Restoring RTC registers.
|
||||
RTC.RCR1->byte = e->RCR1;
|
||||
RTC.RCR2->byte = e->RCR2;
|
||||
|
||||
// Restoring TMU registers.
|
||||
*(TMU.timers[0]) = e->TMU0;
|
||||
*(TMU.timers[1]) = e->TMU1;
|
||||
*(TMU.timers[2]) = e->TMU2;
|
||||
TMU.TSTR->byte = e->TSTR;
|
||||
|
||||
// Restoring keyboard-related I/O port registers. However the backlight
|
||||
// pin is in PNDR and we would like the backlight to persist when we
|
||||
// leave the application, so we just keep this bit.
|
||||
*((volatile uint16_t *)0xa4050116) = e->PMCR;
|
||||
*((volatile uint8_t *)0xa4050136) = e->PMDR;
|
||||
*((volatile uint16_t *)0xa4050118) = e->PNCR;
|
||||
*((volatile uint8_t *)0xa4050138) &= 0x10;
|
||||
*((volatile uint8_t *)0xa4050138) |= (e->PNDR & ~0x10);
|
||||
*((volatile uint16_t *)0xa405014c) = e->PZCR;
|
||||
*((volatile uint8_t *)0xa405016c) = e->PZDR;
|
||||
*((volatile uint8_t *)0xa40501c6) = e->key;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,5 @@
|
|||
//---
|
||||
//
|
||||
// gint core module: sh7705 interrupt handler
|
||||
//
|
||||
// Of course all the work related to interrupts is heavily platform-
|
||||
// dependent. This module handles interrupts and configures the MPU to
|
||||
// save and restore the system's configuration when execution ends.
|
||||
//
|
||||
//---
|
||||
|
||||
#include <internals/gint.h>
|
||||
#include <internals/rtc.h>
|
||||
#include <modules/rtc.h>
|
||||
#include <gint.h>
|
||||
#include <timer.h>
|
||||
#include <7705.h>
|
||||
|
@ -38,74 +28,92 @@ volatile void *gint_reg_7705(gint_register_t reg)
|
|||
|
||||
|
||||
//---
|
||||
// Setup.
|
||||
// Register saves, setup, interrupt locks, register restoration.
|
||||
//---
|
||||
|
||||
static unsigned short iprs[8];
|
||||
static unsigned char rcr2;
|
||||
|
||||
static void gint_priority_lock_7705(void)
|
||||
void gint_save_7705(environment_7705_t *e)
|
||||
{
|
||||
// Saving the interrupt masks from registers IPRA to IPRH.
|
||||
iprs[0] = INTC.IPRA.WORD;
|
||||
iprs[1] = INTC.IPRB.WORD;
|
||||
iprs[2] = INTX.IPRC.WORD;
|
||||
iprs[3] = INTX.IPRD.WORD;
|
||||
iprs[4] = INTX.IPRE.WORD;
|
||||
iprs[5] = INTX.IPRF.WORD;
|
||||
iprs[6] = INTX.IPRG.WORD;
|
||||
iprs[7] = INTX.IPRH.WORD;
|
||||
e->IPR[0] = INTC.IPRA.WORD;
|
||||
e->IPR[1] = INTC.IPRB.WORD;
|
||||
e->IPR[2] = INTX.IPRC.WORD;
|
||||
e->IPR[3] = INTX.IPRD.WORD;
|
||||
e->IPR[4] = INTX.IPRE.WORD;
|
||||
e->IPR[5] = INTX.IPRF.WORD;
|
||||
e->IPR[6] = INTX.IPRG.WORD;
|
||||
e->IPR[7] = INTX.IPRH.WORD;
|
||||
|
||||
// Saving RTC registers.
|
||||
e->RCR1 = RTC.RCR1->byte;
|
||||
e->RCR2 = RTC.RCR2->byte;
|
||||
|
||||
// Saving TMU registers.
|
||||
e->TMU0 = *(TMU.timers[0]);
|
||||
e->TMU1 = *(TMU.timers[1]);
|
||||
e->TMU2 = *(TMU.timers[2]);
|
||||
e->TSTR = TMU.TSTR->byte;
|
||||
|
||||
// Saving port data used to access the keyboard.
|
||||
e->PACR = PFC.PACR.WORD;
|
||||
e->PADR = PA.DR.BYTE;
|
||||
e->PBCR = PFC.PBCR.WORD;
|
||||
e->PBDR = PB.DR.BYTE;
|
||||
e->PMCR = PFC.PMCR.WORD;
|
||||
e->PMDR = PM.DR.BYTE;
|
||||
}
|
||||
|
||||
void gint_lock_and_setup_7705(void)
|
||||
{
|
||||
// Disabling everything by default to avoid receiving an interrupt that
|
||||
// the handler doesn't handle, which would cause the user program to
|
||||
// freeze.
|
||||
INTC.IPRA.WORD = 0x0000;
|
||||
INTC.IPRB.WORD = 0x0000;
|
||||
INTX.IPRC.WORD = 0x0000;
|
||||
INTX.IPRD.WORD = 0x0000;
|
||||
INTX.IPRE.WORD = 0x0000;
|
||||
INTX.IPRF.WORD = 0x0000;
|
||||
INTX.IPRG.WORD = 0x0000;
|
||||
INTX.IPRH.WORD = 0x0000;
|
||||
INTC.IPRA.WORD = 0x0000;
|
||||
INTC.IPRB.WORD = 0x0000;
|
||||
INTX.IPRC.WORD = 0x0000;
|
||||
INTX.IPRD.WORD = 0x0000;
|
||||
INTX.IPRE.WORD = 0x0000;
|
||||
INTX.IPRF.WORD = 0x0000;
|
||||
INTX.IPRG.WORD = 0x0000;
|
||||
INTX.IPRH.WORD = 0x0000;
|
||||
|
||||
// Allowing RTC, which handles keyboard.
|
||||
// Allowing RTC and timer (which handles keyboard and a whole bunch of
|
||||
// other things).
|
||||
INTC.IPRA.BIT._RTC = 10;
|
||||
INTC.IPRA.BIT._TMU0 = 12;
|
||||
INTC.IPRA.BIT._TMU1 = 12;
|
||||
INTC.IPRA.BIT._TMU2 = 12;
|
||||
|
||||
// Don't enable RTC periodic signals by default.
|
||||
RTC.RCR2->byte = 0x09;
|
||||
}
|
||||
|
||||
static void gint_priority_unlock_7705(void)
|
||||
void gint_restore_and_unlock_7705(environment_7705_t *e)
|
||||
{
|
||||
// Restoring the saved states.
|
||||
INTC.IPRA.WORD = iprs[0];
|
||||
INTC.IPRB.WORD = iprs[1];
|
||||
INTX.IPRC.WORD = iprs[2];
|
||||
INTX.IPRD.WORD = iprs[3];
|
||||
INTX.IPRE.WORD = iprs[4];
|
||||
INTX.IPRF.WORD = iprs[5];
|
||||
INTX.IPRG.WORD = iprs[6];
|
||||
INTX.IPRH.WORD = iprs[7];
|
||||
}
|
||||
|
||||
void gint_setup_7705(void)
|
||||
{
|
||||
volatile struct mod_rtc *RTC = RTC_SH7705;
|
||||
|
||||
gint_priority_lock_7705();
|
||||
|
||||
// Saving the RTC configuration.
|
||||
rcr2 = RTC->RCR2.BYTE;
|
||||
// Disabling RTC interrupts by default.
|
||||
RTC->RCR2.BYTE = 0x09;
|
||||
}
|
||||
|
||||
void gint_stop_7705(void)
|
||||
{
|
||||
volatile struct mod_rtc *RTC = RTC_SH7705;
|
||||
|
||||
gint_priority_unlock_7705();
|
||||
|
||||
// Restoring the RTC configuration.
|
||||
RTC->RCR2.BYTE = rcr2;
|
||||
INTC.IPRA.WORD = e->IPR[0];
|
||||
INTC.IPRB.WORD = e->IPR[1];
|
||||
INTX.IPRC.WORD = e->IPR[2];
|
||||
INTX.IPRD.WORD = e->IPR[3];
|
||||
INTX.IPRE.WORD = e->IPR[4];
|
||||
INTX.IPRF.WORD = e->IPR[5];
|
||||
INTX.IPRG.WORD = e->IPR[6];
|
||||
INTX.IPRH.WORD = e->IPR[7];
|
||||
|
||||
// Restoring RTC registers.
|
||||
RTC.RCR1->byte = e->RCR1;
|
||||
RTC.RCR2->byte = e->RCR2;
|
||||
|
||||
// Restoring TMU registers.
|
||||
*(TMU.timers[0]) = e->TMU0;
|
||||
*(TMU.timers[1]) = e->TMU1;
|
||||
*(TMU.timers[2]) = e->TMU2;
|
||||
TMU.TSTR->byte = e->TSTR;
|
||||
|
||||
// Restoring keyboard-related I/O port registers.
|
||||
PFC.PACR.WORD = e->PACR;
|
||||
PA.DR.BYTE = e->PADR;
|
||||
PFC.PBCR.WORD = e->PBCR;
|
||||
PB.DR.BYTE = e->PBDR;
|
||||
PFC.PMCR.WORD = e->PMCR;
|
||||
PM.DR.BYTE = e->PMDR;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ _gint_setvbr:
|
|||
jsr @r5
|
||||
nop
|
||||
|
||||
/* Activating interrupts again. */
|
||||
/* Enabling interrupts again. */
|
||||
mov.l sr_block, r0
|
||||
not r0, r0
|
||||
stc sr, r3
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#include <internals/gint.h>
|
||||
#include <internals/interrupt_maps.h>
|
||||
#include <internals/modules.h>
|
||||
#include <gint.h>
|
||||
#include <mpu.h>
|
||||
|
||||
gint_info_t gint;
|
||||
static environment_t env;
|
||||
|
||||
//---
|
||||
// Initialization routines
|
||||
|
@ -16,10 +18,17 @@ gint_info_t gint;
|
|||
*/
|
||||
static void setup(void)
|
||||
{
|
||||
isSH3() ? gint_setup_7705() : gint_setup_7305();
|
||||
isSH3() ? gint_lock_and_setup_7705()
|
||||
: gint_lock_and_setup_7305();
|
||||
}
|
||||
void gint_init(void)
|
||||
{
|
||||
// Detecting the MPU type. I don't like const-casting but this is still
|
||||
// better than allowing the user to change the variable by mistake.
|
||||
*((mpu_t *)&MPU_CURRENT) = getMPU();
|
||||
// Loading the register addresses of the current platform.
|
||||
mod_init();
|
||||
|
||||
// Linker script symbols -- gint.
|
||||
extern uint32_t
|
||||
gint_vbr,
|
||||
|
@ -32,6 +41,9 @@ void gint_init(void)
|
|||
// Loading the interrupt handler into the memory.
|
||||
while(ptr < &egint) *ptr++ = *src++;
|
||||
|
||||
isSH3() ? gint_save_7705(&env.env_7705)
|
||||
: gint_save_7305(&env.env_7305);
|
||||
|
||||
// Installing gint's default exception/interrupt handlers.
|
||||
for(int i = 0; i < exc_type_max; i++)
|
||||
{
|
||||
|
@ -59,7 +71,8 @@ void gint_init(void)
|
|||
*/
|
||||
static void stop(void)
|
||||
{
|
||||
isSH3() ? gint_stop_7705() : gint_stop_7305();
|
||||
isSH3() ? gint_restore_and_unlock_7705(&env.env_7705)
|
||||
: gint_restore_and_unlock_7305(&env.env_7305);
|
||||
}
|
||||
void gint_quit(void)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include <modules/timer.h>
|
||||
#include <modules/rtc.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <mpu.h>
|
||||
|
||||
|
@ -11,7 +13,8 @@
|
|||
// confront to the hardware directly.
|
||||
//---
|
||||
|
||||
volatile mod_tmu_t TMU;
|
||||
mod_tmu_t TMU;
|
||||
mod_rtc_t RTC;
|
||||
|
||||
|
||||
|
||||
|
@ -26,6 +29,10 @@ static void mod_init_7705(void)
|
|||
TMU.timers[2] = (void *)0xfffffeac;
|
||||
TMU.TSTR = (void *)0xfffffe92;
|
||||
TMU.TCPR2 = (void *)0xfffffeb8;
|
||||
|
||||
RTC.RCR1 = (void *)0xfffffedc;
|
||||
RTC.RCR2 = (void *)0xfffffede;
|
||||
RTC.time = (void *)0xfffffec0;
|
||||
}
|
||||
|
||||
static void mod_init_7305(void)
|
||||
|
@ -35,6 +42,10 @@ static void mod_init_7305(void)
|
|||
TMU.timers[2] = (void *)0xa4490020;
|
||||
TMU.TSTR = (void *)0xa4490004;
|
||||
TMU.TCPR2 = NULL;
|
||||
|
||||
RTC.RCR1 = (void *)0xa413fedc;
|
||||
RTC.RCR2 = (void *)0xa413fede;
|
||||
RTC.time = (void *)0xa413fec0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <mpu.h>
|
||||
|
||||
mpu_t MPU_CURRENT;
|
||||
const mpu_t MPU_CURRENT;
|
||||
|
||||
/*
|
||||
getMPU()
|
||||
|
@ -67,14 +67,3 @@ mpu_t getMPU(void)
|
|||
// By default, the MPU is unknown.
|
||||
return mpu_unknown;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mpu_init()
|
||||
Determines the MPU type and stores the result into MPU_CURRENT.
|
||||
*/
|
||||
__attribute__((constructor)) void mpu_init(void)
|
||||
{
|
||||
MPU_CURRENT = getMPU();
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
many keys on the same column are pressed, other keys of the same column
|
||||
may be triggered.
|
||||
|
||||
(The following values do not apply to the latest tests, even if the
|
||||
trend remains the same.)
|
||||
- Less Bad key detection.
|
||||
- 8 Very few column effects. Most often, three keys may be pressed
|
||||
simultaneously. However, [UP] has latencies and is globally not
|
||||
|
@ -49,7 +51,8 @@ static void kdelay(void)
|
|||
|
||||
__asm__
|
||||
(
|
||||
"nop\n\t"
|
||||
r4(r4("nop\n\t"))
|
||||
r4(r4("nop\n\t"))
|
||||
);
|
||||
|
||||
#undef r4
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#include <internals/rtc.h>
|
||||
#include <modules/rtc.h>
|
||||
#include <rtc.h>
|
||||
#include <mpu.h>
|
||||
|
||||
// Array holding callback informations.
|
||||
struct rtc_cb cb_array[RTC_CB_ARRAY_SIZE] = { 0 };
|
||||
rtc_callback_t cb_array[RTC_CB_ARRAY_SIZE] = { 0 };
|
||||
// Callback identifier (unique).
|
||||
static int unique_id = 1;
|
||||
// Current RTC interrupt frequency.
|
||||
static rtc_frequency_t rtc_freq = RTCFreq_None;
|
||||
static rtc_frequency_t rtc_freq = rtc_freq_none;
|
||||
// 256-Hz tick count. This counter is stopped when no callback is registered.
|
||||
static unsigned elapsed256 = 0;
|
||||
|
||||
|
@ -21,7 +22,7 @@ static unsigned elapsed256 = 0;
|
|||
*/
|
||||
static void rtc_cb_update(void)
|
||||
{
|
||||
rtc_frequency_t max = RTCFreq_None;
|
||||
rtc_frequency_t max = rtc_freq_none;
|
||||
int n;
|
||||
|
||||
for(n = 0; n < RTC_CB_ARRAY_SIZE; n++) if(cb_array[n].id)
|
||||
|
@ -33,8 +34,7 @@ static void rtc_cb_update(void)
|
|||
if(rtc_freq == max) return;
|
||||
rtc_freq = max;
|
||||
|
||||
volatile struct mod_rtc *RTC = isSH3() ? RTC_SH7705 : RTC_SH7305;
|
||||
RTC->RCR2.BYTE = (rtc_freq << 4) | 0x09;
|
||||
RTC.RCR2->byte = (rtc_freq << 4) | 0x09;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -49,7 +49,7 @@ static void rtc_cb_update(void)
|
|||
int rtc_cb_add(rtc_frequency_t freq, void (*function)(void), int repeats)
|
||||
{
|
||||
int n = 0;
|
||||
if(freq == RTCFreq_None || !function || repeats < 0) return -2;
|
||||
if(freq == rtc_freq_none || !function || repeats < 0) return -2;
|
||||
|
||||
while(n < RTC_CB_ARRAY_SIZE && cb_array[n].id) n++;
|
||||
if(n >= RTC_CB_ARRAY_SIZE) return -1;
|
||||
|
@ -77,7 +77,7 @@ void rtc_cb_end(int id)
|
|||
if(n >= RTC_CB_ARRAY_SIZE) return;
|
||||
|
||||
cb_array[n].id = 0;
|
||||
cb_array[n].freq = RTCFreq_None;
|
||||
cb_array[n].freq = rtc_freq_none;
|
||||
cb_array[n].callback = NULL;
|
||||
cb_array[n].repeats = 0;
|
||||
|
||||
|
@ -134,7 +134,7 @@ void rtc_cb_interrupt(void)
|
|||
|
||||
for(n = 0; n < RTC_CB_ARRAY_SIZE; n++)
|
||||
{
|
||||
struct rtc_cb *cb = &cb_array[n];
|
||||
rtc_callback_t *cb = &cb_array[n];
|
||||
if(!cb->id || !cb->freq) continue;
|
||||
|
||||
// Only execute callback when the number of elapsed 256-Hz
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
#include <internals/rtc.h>
|
||||
#include <modules/rtc.h>
|
||||
#include <rtc.h>
|
||||
#include <mpu.h>
|
||||
|
||||
/*
|
||||
integer()
|
||||
integer8(), integer16() [static]
|
||||
Converts a BCD value to an integer.
|
||||
*/
|
||||
static int integer8(int bcd)
|
||||
static int integer8(uint8_t bcd)
|
||||
{
|
||||
return (bcd & 0x0f) + 10 * (bcd >> 4);
|
||||
}
|
||||
static int integer16(int bcd)
|
||||
static int integer16(uint16_t bcd)
|
||||
{
|
||||
return (bcd & 0xf) + 10 * ((bcd >> 4) & 0xf) + 100 * ((bcd >> 8) & 0xf)
|
||||
+ 1000 * (bcd >> 12);
|
||||
|
@ -19,26 +20,23 @@ static int integer16(int bcd)
|
|||
/*
|
||||
rtc_getTime()
|
||||
Reads the current time from the RTC. There is no guarantee that the
|
||||
week day is correct (use the time API for that).
|
||||
week day will contain a correct value (use the time API for that).
|
||||
*/
|
||||
rtc_time_t rtc_getTime(void)
|
||||
void rtc_getTime(rtc_time_t *time)
|
||||
{
|
||||
volatile struct mod_rtc *rtc = isSH3() ? RTC_SH7705 : RTC_SH7305;
|
||||
rtc_time_t time;
|
||||
if(!time) return;
|
||||
|
||||
do
|
||||
{
|
||||
rtc->RCR1.CF = 0;
|
||||
RTC.RCR1->CF = 0;
|
||||
|
||||
time.seconds = integer8(rtc->RSECCNT.BYTE);
|
||||
time.minutes = integer8(rtc->RMINCNT.BYTE);
|
||||
time.hours = integer8(rtc->RHRCNT.BYTE);
|
||||
time.month_day = integer8(rtc->RDAYCNT.BYTE);
|
||||
time.month = integer8(rtc->RMONCNT.BYTE);
|
||||
time.year = integer16(rtc->RYRCNT.WORD);
|
||||
time.week_day = rtc->RWKCNT;
|
||||
time->seconds = integer8(RTC.time->RSECCNT.byte);
|
||||
time->minutes = integer8(RTC.time->RMINCNT.byte);
|
||||
time->hours = integer8(RTC.time->RHRCNT .byte);
|
||||
time->month_day = integer8(RTC.time->RDAYCNT.byte);
|
||||
time->month = integer8(RTC.time->RMONCNT.byte);
|
||||
time->year = integer16(RTC.time->RYRCNT.word);
|
||||
time->week_day = RTC.time->RWKCNT;
|
||||
}
|
||||
while(rtc->RCR1.CF != 0);
|
||||
|
||||
return time;
|
||||
while(RTC.RCR1->CF != 0);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#include <internals/rtc.h>
|
||||
#include <modules/rtc.h>
|
||||
#include <rtc.h>
|
||||
#include <mpu.h>
|
||||
|
||||
int rtc_carry_flag = 0;
|
||||
|
||||
/*
|
||||
rtc_periodic_interrupt()
|
||||
Handles an RTC interrupt by calling the callback.
|
||||
|
@ -12,6 +11,5 @@ void rtc_periodic_interrupt(void)
|
|||
{
|
||||
rtc_cb_interrupt();
|
||||
|
||||
volatile struct mod_rtc *RTC = isSH3() ? RTC_SH7705 : RTC_SH7305;
|
||||
RTC->RCR2.PEF = 0;
|
||||
RTC.RCR2->PEF = 0;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
#include <internals/rtc.h>
|
||||
#include <modules/rtc.h>
|
||||
#include <rtc.h>
|
||||
#include <mpu.h>
|
||||
|
||||
/*
|
||||
bcd()
|
||||
bcd8(), bcd16() [static]
|
||||
Converts an integer to a BCD value.
|
||||
*/
|
||||
static int bcd8(int integer)
|
||||
static uint8_t bcd8(int integer)
|
||||
{
|
||||
integer %= 100;
|
||||
return ((integer / 10) << 4) | (integer % 10);
|
||||
}
|
||||
static int bcd16(int integer)
|
||||
static uint16_t bcd16(int integer)
|
||||
{
|
||||
integer %= 10000;
|
||||
return (bcd8(integer / 100) << 8) | bcd8(integer % 100);
|
||||
|
@ -22,22 +23,22 @@ static int bcd16(int integer)
|
|||
Sets the time in the RTC registers. The week day is set to 0 if greater
|
||||
than 6. Other fields are not checked.
|
||||
*/
|
||||
void rtc_setTime(rtc_time_t time)
|
||||
void rtc_setTime(const rtc_time_t *time)
|
||||
{
|
||||
volatile struct mod_rtc *rtc = isSH3() ? RTC_SH7705 : RTC_SH7305;
|
||||
int wday = (time.week_day < 7) ? (time.week_day) : (0);
|
||||
if(!time) return;
|
||||
int wday = (time->week_day < 7) ? (time->week_day) : (0);
|
||||
|
||||
do
|
||||
{
|
||||
rtc->RCR1.CF = 0;
|
||||
RTC.RCR1->CF = 0;
|
||||
|
||||
rtc->RSECCNT.BYTE = bcd8(time.seconds);
|
||||
rtc->RMINCNT.BYTE = bcd8(time.minutes);
|
||||
rtc->RHRCNT.BYTE = bcd8(time.hours);
|
||||
rtc->RDAYCNT.BYTE = bcd8(time.month_day);
|
||||
rtc->RMONCNT.BYTE = bcd8(time.month);
|
||||
rtc->RYRCNT.WORD = bcd16(time.year);
|
||||
rtc->RWKCNT = wday;
|
||||
RTC.time->RSECCNT.byte = bcd8(time->seconds);
|
||||
RTC.time->RMINCNT.byte = bcd8(time->minutes);
|
||||
RTC.time->RHRCNT .byte = bcd8(time->hours);
|
||||
RTC.time->RDAYCNT.byte = bcd8(time->month_day);
|
||||
RTC.time->RMONCNT.byte = bcd8(time->month);
|
||||
RTC.time->RYRCNT .word = bcd16(time->year);
|
||||
RTC.time->RWKCNT = wday;
|
||||
}
|
||||
while(rtc->RCR1.CF != 0);
|
||||
while(RTC.RCR1->CF != 0);
|
||||
}
|
||||
|
|
|
@ -12,10 +12,11 @@
|
|||
*/
|
||||
time_t time(time_t *timeptr)
|
||||
{
|
||||
rtc_time_t rtc = rtc_getTime();
|
||||
rtc_time_t rtc;
|
||||
struct tm tm;
|
||||
time_t calendar;
|
||||
|
||||
rtc_getTime(&rtc);
|
||||
tm.tm_sec = rtc.seconds;
|
||||
tm.tm_min = rtc.minutes;
|
||||
tm.tm_hour = rtc.hours;
|
||||
|
|
1
version
Normal file
1
version
Normal file
|
@ -0,0 +1 @@
|
|||
beta-0.9-289
|
Loading…
Reference in a new issue