mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-29 13:03:36 +01:00
More quality review, more registers saved at startup.
This commit is contained in:
parent
c8170b165a
commit
acc0e5fcc1
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:
|
# 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
|
# Generic rules
|
||||||
|
@ -142,16 +164,20 @@ build:
|
||||||
$(if $(VERBOSE),,@ printf '\e[35;1mdir \u00bb\e[0m mkdir $@\n')
|
$(if $(VERBOSE),,@ printf '\e[35;1mdir \u00bb\e[0m mkdir $@\n')
|
||||||
$(if $(VERBOSE),,@) mkdir -p $@
|
$(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
|
$(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),,@ printf '\e[35;1mlib \u00bb\e[0m ar $@\n')
|
||||||
$(if $(VERBOSE),,@) $(ar) rcs $@ $(obj-std)
|
$(if $(VERBOSE),,@) $(ar) rcs $@ $(obj-std)
|
||||||
@ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built libc ('
|
@ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built libc ('
|
||||||
@ printf $$(stat -c %s $@)
|
@ printf $$(stat -c %s $@)
|
||||||
@ printf ' bytes)\n\n'
|
@ 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),,@ printf '\e[35;1mlib \u00bb\e[0m ar $@\n')
|
||||||
$(if $(VERBOSE),,@) $(ar) rcs $@ $(obj-lib)
|
$(if $(VERBOSE),,@) $(ar) rcs $@ $(obj-lib)
|
||||||
@ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built libgint ('
|
@ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built libgint ('
|
||||||
|
|
44
TODO
44
TODO
|
@ -1,37 +1,37 @@
|
||||||
Bugs to fix:
|
Bugs to fix:
|
||||||
- A few key hits ignored after leaving the application (could not reproduce)
|
- A few key hits ignored after leaving the application (could not reproduce)
|
||||||
- Lost keyboard control at startup (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
|
- Alignment of ALL .data / .rodata files is required to ensure converted data
|
||||||
is properly aligned
|
is properly aligned
|
||||||
|
- Reported video ram overflow when rendering text at borderline positions
|
||||||
|
|
||||||
Simple improvements:
|
Things to do before 1.0:
|
||||||
- demo: Try 284x124 at (-60, -28) (all disadvantages)
|
- bopti: Test partial transparency
|
||||||
- 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
|
|
||||||
* core: Allow return to menu
|
* core: Allow return to menu
|
||||||
- serial: Implement a driver
|
- demo: Try 284x124 at (-60, -28) (all disadvantages)
|
||||||
- usb: Implement a driver
|
- display: Implement rectangle-based drawing functions
|
||||||
- esper: Cleaner playback, synthesizing
|
- project: Add a real build-based version system
|
||||||
- clock: Handle overclock (relaunch clocks when overclocking)
|
- project: Check size of *all* library structures
|
||||||
|
- project: Clean headers that have some internal definitions
|
||||||
- project: Unify this hellish mess of register access!
|
- 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:
|
Things to investigate:
|
||||||
- Packed bit fields alignment
|
- Packed bit fields alignment
|
||||||
- Registers that may need to be saved within setjmp()
|
- 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
|
- 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,
|
running the interrupt handler, although it ends on rte; lds.l @r15+, mach,
|
||||||
which is totally not an illegal slot.
|
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)
|
switch(tab)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
locate(1, 1, "Demo application");
|
print(1, 1, "Demo application");
|
||||||
print(2, 3, "gint version: %5s", GINT_VERSION_STR);
|
// print(2, 3, "gint version: %5s", GINT_VERSION_STR);
|
||||||
print(2, 4, "handler size: %5d", gint_size);
|
print(2, 4, "handler size: %5d", gint_size);
|
||||||
print(2, 5, "mpu type: %7s", mpu);
|
print(2, 5, "mpu type: %7s", mpu);
|
||||||
print(2, 6, "romdata: %08x", &romdata);
|
print(2, 6, "romdata: %08x", &romdata);
|
||||||
|
|
|
@ -95,14 +95,10 @@ static image_t *select(image_t *current)
|
||||||
8 * i, 7, 7);
|
8 * i, 7, 7);
|
||||||
if(i == row)
|
if(i == row)
|
||||||
{
|
{
|
||||||
print(2, 2 + i + 1, "%08x", (unsigned int)
|
|
||||||
images[i].img);
|
|
||||||
/*
|
|
||||||
int width, height;
|
int width, height;
|
||||||
getwh(images[i].img, &width, &height);
|
getwh(images[i].img, &width, &height);
|
||||||
print(2, 2 + i + 1, "%d\x04%d", width, height);
|
print(2, 2 + i + 1, "%d\x04%d", width, height);
|
||||||
locate(10, 2 + i + 1, images[i].info);
|
locate(10, 2 + i + 1, images[i].info);
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +143,7 @@ void test_bopti(void)
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
if(img && (img->format & Channel_Light))
|
if(img && (img->format & channel_light))
|
||||||
{
|
{
|
||||||
gray_start();
|
gray_start();
|
||||||
gclear();
|
gclear();
|
||||||
|
|
|
@ -14,9 +14,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <internals/rtc.h>
|
#include <internals/rtc.h>
|
||||||
|
#include <modules/rtc.h>
|
||||||
#include <mpu.h>
|
#include <mpu.h>
|
||||||
|
|
||||||
static void draw(rtc_time_t time)
|
static void draw(rtc_time_t *time)
|
||||||
{
|
{
|
||||||
extern image_t res_rtc_segments;
|
extern image_t res_rtc_segments;
|
||||||
|
|
||||||
|
@ -30,12 +31,12 @@ static void draw(rtc_time_t time)
|
||||||
int digits[6];
|
int digits[6];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
digits[0] = time.hours / 10;
|
digits[0] = time->hours / 10;
|
||||||
digits[1] = time.hours % 10;
|
digits[1] = time->hours % 10;
|
||||||
digits[2] = time.minutes / 10;
|
digits[2] = time->minutes / 10;
|
||||||
digits[3] = time.minutes % 10;
|
digits[3] = time->minutes % 10;
|
||||||
digits[4] = time.seconds / 10;
|
digits[4] = time->seconds / 10;
|
||||||
digits[5] = time.seconds % 10;
|
digits[5] = time->seconds % 10;
|
||||||
|
|
||||||
// Drawing digits.
|
// Drawing digits.
|
||||||
for(i = 0; i < 6; i++) dimage_part(x[i], 8, &res_rtc_segments,
|
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
|
// 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.
|
// have tweaked the field so that it already contains time.year + 1900.
|
||||||
print(4, 6, "%s %s %02d %4d", days[time.week_day],
|
print(4, 6, "%s %s %02d %4d", days[time->week_day],
|
||||||
months[time.month], time.month_day, time.year);
|
months[time->month], time->month_day, time->year);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void callback(void)
|
static void callback(void)
|
||||||
{
|
{
|
||||||
extern image_t res_opt_rtc;
|
extern image_t res_opt_rtc;
|
||||||
rtc_time_t time = rtc_getTime();
|
rtc_time_t time;
|
||||||
|
rtc_getTime(&time);
|
||||||
|
|
||||||
dclear();
|
dclear();
|
||||||
draw(time);
|
draw(&time);
|
||||||
dimage_part(0, 56, &res_opt_rtc, 0, 0, 19, 8);
|
dimage_part(0, 56, &res_opt_rtc, 0, 0, 19, 8);
|
||||||
dupdate();
|
dupdate();
|
||||||
}
|
}
|
||||||
|
@ -128,14 +130,16 @@ static void set(void)
|
||||||
{ 72, 39, 7, 9 }, { 84, 39, 7, 9 }, { 90, 39, 7, 9 },
|
{ 72, 39, 7, 9 }, { 84, 39, 7, 9 }, { 90, 39, 7, 9 },
|
||||||
{ 96, 39, 7, 9 }, { 102, 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 region_count = 14;
|
||||||
int n = 0, slide = 0, key, leave;
|
int n = 0, slide = 0, key, leave;
|
||||||
|
|
||||||
|
rtc_getTime(&time);
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
dclear();
|
dclear();
|
||||||
draw(time);
|
draw(&time);
|
||||||
drect(regions[n].x, regions[n].y, regions[n].x + regions[n].w
|
drect(regions[n].x, regions[n].y, regions[n].x + regions[n].w
|
||||||
- 1, regions[n].y + regions[n].h - 1, color_invert);
|
- 1, regions[n].y + regions[n].h - 1, color_invert);
|
||||||
|
|
||||||
|
@ -157,7 +161,7 @@ static void set(void)
|
||||||
slide = 0;
|
slide = 0;
|
||||||
if(++n == region_count)
|
if(++n == region_count)
|
||||||
{
|
{
|
||||||
rtc_setTime(time);
|
rtc_setTime(&time);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,7 +220,7 @@ static void set(void)
|
||||||
n++;
|
n++;
|
||||||
if(n == region_count)
|
if(n == region_count)
|
||||||
{
|
{
|
||||||
rtc_setTime(time);
|
rtc_setTime(&time);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
slide = 0;
|
slide = 0;
|
||||||
|
@ -235,7 +239,7 @@ void test_rtc(void)
|
||||||
{
|
{
|
||||||
int key, cb_id;
|
int key, cb_id;
|
||||||
|
|
||||||
cb_id = rtc_cb_add(RTCFreq_1Hz, callback, 0);
|
cb_id = rtc_cb_add(rtc_freq_1Hz, callback, 0);
|
||||||
callback();
|
callback();
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
|
@ -245,10 +249,10 @@ void test_rtc(void)
|
||||||
if(key == KEY_EXIT) break;
|
if(key == KEY_EXIT) break;
|
||||||
if(key == KEY_F1)
|
if(key == KEY_F1)
|
||||||
{
|
{
|
||||||
rtc_cb_edit(cb_id, RTCFreq_None, NULL);
|
rtc_cb_edit(cb_id, rtc_freq_none, NULL);
|
||||||
set();
|
set();
|
||||||
callback();
|
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_attach(htimer, timing_timer, NULL);
|
||||||
timer_start(htimer);
|
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_timer = 0;
|
||||||
elapsed_rtc = 0;
|
elapsed_rtc = 0;
|
||||||
|
@ -247,7 +247,7 @@ void test_timer(void)
|
||||||
|
|
||||||
elapsed_timer = -1;
|
elapsed_timer = -1;
|
||||||
elapsed_rtc = -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);
|
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
|
Point (left, top) is included, but (left + width, top + height) is
|
||||||
excluded.
|
excluded.
|
||||||
*/
|
*/
|
||||||
void dimage_part(int x, int y, image_t *img, int left, int top, int width,
|
void dimage_part(
|
||||||
int height);
|
int x, int y,
|
||||||
|
image_t *img,
|
||||||
|
int left, int top, int width, int height
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
gimage()
|
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
|
Point (left, top) is included, but (left + width, top + height) is
|
||||||
excluded.
|
excluded.
|
||||||
*/
|
*/
|
||||||
void gimage_part(int x, int y, image_t *image, int left, int top, int width,
|
void gimage_part(
|
||||||
int height);
|
int x, int y,
|
||||||
|
image_t *image,
|
||||||
|
int left, int top, int width, int height
|
||||||
|
);
|
||||||
|
|
||||||
#endif // _BOPTI_H
|
#endif // _BOPTI_H
|
||||||
|
|
|
@ -15,9 +15,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define GINT_VERSION 0x000100a3
|
|
||||||
#define GINT_VERSION_STR "00.01"
|
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// System info provided by the library
|
// 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
|
#ifndef _INTERNALS_BOPTI_H
|
||||||
#define _INTERNALS_BOPTI_H
|
#define _INTERNALS_BOPTI_H
|
||||||
|
|
||||||
|
@ -21,40 +5,45 @@
|
||||||
#include <display.h>
|
#include <display.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
enum Channel
|
channel_t
|
||||||
Determines the kind of information written into a layer. Every image is
|
Indicates what operation a layer is made for. Each operation affects
|
||||||
made of one or more channels.
|
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_full_alpha = 0x01,
|
||||||
Channel_LightAlpha = 0x02,
|
channel_light_alpha = 0x02,
|
||||||
Channel_DarkAlpha = 0x04,
|
channel_dark_alpha = 0x04,
|
||||||
|
|
||||||
Channel_Mono = 0x08,
|
channel_mono = 0x08,
|
||||||
Channel_Light = 0x10,
|
channel_light = 0x10,
|
||||||
Channel_Dark = 0x20,
|
channel_dark = 0x20,
|
||||||
};
|
|
||||||
|
} channel_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
enum Format
|
format_t
|
||||||
Describes the various combination of channels allowed by bopti.
|
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_mono = channel_mono,
|
||||||
Format_MonoAlpha = Format_Mono | Channel_FullAlpha,
|
format_mono_alpha = format_mono | channel_full_alpha,
|
||||||
Format_Gray = Channel_Light | Channel_Dark,
|
format_gray = channel_light | channel_dark,
|
||||||
Format_GrayAlpha = Format_Gray | Channel_FullAlpha,
|
format_gray_alpha = format_gray | channel_full_alpha,
|
||||||
Format_GreaterAlpha = Format_Mono | Channel_LightAlpha |
|
format_greater_alpha = format_mono | channel_light_alpha |
|
||||||
Channel_DarkAlpha
|
channel_dark_alpha
|
||||||
};
|
} format_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
struct Structure
|
structure_t
|
||||||
Describes an image's structure.
|
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 width, height;
|
||||||
int layer_size;
|
int layer_size;
|
||||||
|
@ -62,26 +51,37 @@ struct Structure
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
int columns;
|
int columns;
|
||||||
int end_size, end_bytes;
|
int end_size, end_bytes;
|
||||||
};
|
|
||||||
|
} structure_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
struct Command
|
command_t
|
||||||
Contains a drawing operation's parameters.
|
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.
|
// Channel being drawn.
|
||||||
enum Channel channel;
|
channel_t channel;
|
||||||
// Operation used (whether bopti_op_mono() or bopti_op_gray()).
|
// 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
|
// Portion of the bitmap which is drawn. 'top' and 'bottom' refer to
|
||||||
// lines where 'left' and 'right' refer to column ids.
|
// lines where 'left' and 'right' refer to column ids.
|
||||||
int left, right, top, bottom;
|
int left, right, top, bottom;
|
||||||
// Position of the bitmap on the screen.
|
// Position of the bitmap on the screen.
|
||||||
int x, y;
|
int x, y;
|
||||||
// Rectangle masks.
|
// Rectangle masks that define the drawing area.
|
||||||
uint32_t masks[4];
|
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
|
// The video ram addresses are set by the public functions and used internally
|
||||||
// by the module.
|
// 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
|
image information. Since neutral bits are not the same for all
|
||||||
operations, a mask is used to indicate which bits should be used for
|
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
|
the operation. This mask is taken for the image's rectangle masks (see
|
||||||
module display for more information on rectangle masks).
|
the 'display' module internal header for more information on rectangle
|
||||||
Which operation is performed is determined by the channel setting.
|
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_mono(int offset, uint32_t operator, command_t *c);
|
||||||
void bopti_op_gray(int offset, uint32_t operator, struct Command *c);
|
void bopti_op_gray(int offset, uint32_t operator, command_t *c);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bopti_grid() -- general form
|
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,
|
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
|
because bopti_grid() will perform a 32-bit shift when x is a multiple
|
||||||
of 32, which is undefined behavior.
|
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,
|
void bopti_grid_a32(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,
|
void bopti_grid(const uint32_t *layer, int columns, int height, command_t *c);
|
||||||
struct Command *c);
|
|
||||||
/*
|
/*
|
||||||
bopti_end_get()
|
bopti_end_get()
|
||||||
Returns an operator for the end of a line, whose width is lower than 32
|
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
|
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;
|
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
|
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
|
Unlike bopti_grid_a32(), bopti_end_nover() is not called automatically
|
||||||
by bopti_end().
|
by bopti_end().
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
void bopti_end(const unsigned char *end, int size, struct Command *c);
|
void bopti_end(const unsigned char *end, int size, command_t *c);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bopti()
|
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()
|
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
|
#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);
|
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()
|
gint_save()
|
||||||
Saves many registers into a buffer to ensure that the system is not
|
Saves many registers into an internal environment buffer.
|
||||||
upset by gint's configuration when the application ends.
|
|
||||||
*/
|
*/
|
||||||
// void gint_save_7705(gint_save_buffer_t *buffer);
|
void gint_save_7705(environment_7705_t *env);
|
||||||
// void gint_save_7305(gint_save_buffer_t *buffer);
|
void gint_save_7305(environment_7305_t *env);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
gint_setup()
|
gint_lock_and_setup()
|
||||||
Configures interrupt priorities and some parameters to allow gint to
|
Locks all interrupts (ie. disables them by default) and sets initial
|
||||||
take control of the interrupt flow.
|
values to all registers, allows specific interrupts, etc.
|
||||||
*/
|
*/
|
||||||
void gint_setup_7705(void);
|
void gint_lock_and_setup_7705(void);
|
||||||
void gint_setup_7305(void);
|
void gint_lock_and_setup_7305(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
gint_restore()
|
gint_restore_and_unlock()
|
||||||
Restores the parameters saved in a save buffer to give back the
|
Restores the parameters saved in the environment buffer to give back
|
||||||
interrupt control to the system.
|
the interrupt control to the system.
|
||||||
*/
|
*/
|
||||||
// void gint_restore_7705(gint_save_buffer_t *buffer);
|
void gint_restore_and_unlock_7705(environment_7705_t *env);
|
||||||
// void gint_restore_7305(gint_save_buffer_t *buffer);
|
void gint_restore_and_unlock_7305(environment_7305_t *env);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
gint_reg()
|
gint_reg()
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
#include <timer.h>
|
#include <timer.h>
|
||||||
#include <clock.h>
|
#include <clock.h>
|
||||||
|
|
||||||
// Keyboard variables.
|
// Current keyboard state and keyboard interrupt flag.
|
||||||
extern volatile uint8_t keyboard_state[10];
|
extern volatile uint8_t keyboard_state[10];
|
||||||
extern volatile int interrupt_flag;
|
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 repeat_first, repeat_next;
|
||||||
extern int last_key, last_repeats, last_time;
|
extern int last_key, last_repeats, last_time;
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
// gint core module: mmu
|
// gint core module: mmu
|
||||||
//
|
//
|
||||||
// A wise application should avoid tampering with the system's
|
// A wise application should avoid tampering with the system's
|
||||||
// configuration of the MMU and the TLB. This module implicitly calls the
|
// configuration of the MMU and the TLB. This module implicitly forces the
|
||||||
// system but does nothing by itself.
|
// system to load the required pages but does not interact with the TLB.
|
||||||
//
|
//
|
||||||
//---
|
//---
|
||||||
|
|
||||||
|
|
|
@ -9,20 +9,21 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
struct rtc_cb
|
rtc_callback_t
|
||||||
An RTC callback.
|
An RTC callback with a unique id.
|
||||||
*/
|
*/
|
||||||
struct rtc_cb
|
typedef struct
|
||||||
{
|
{
|
||||||
rtc_frequency_t freq;
|
rtc_frequency_t freq;
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
void (*callback)(void);
|
void (*callback)(void);
|
||||||
int repeats;
|
int repeats;
|
||||||
};
|
|
||||||
|
} rtc_callback_t;
|
||||||
|
|
||||||
// The callback array.
|
// The callback array.
|
||||||
struct rtc_cb cb_array[RTC_CB_ARRAY_SIZE];
|
rtc_callback_t cb_array[RTC_CB_ARRAY_SIZE];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
rtc_perodic_interrupt()
|
rtc_perodic_interrupt()
|
||||||
|
@ -37,118 +38,4 @@ void rtc_periodic_interrupt(void);
|
||||||
*/
|
*/
|
||||||
void rtc_cb_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
|
#endif // _INTERNALS_RTC_H
|
||||||
|
|
|
@ -3,6 +3,15 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#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.
|
// Fixed-width types for bit field are totally meaningless.
|
||||||
typedef unsigned uint;
|
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
|
// The actual thing is there. It's initialized by gint at startup and contains
|
||||||
// addresses and information suitable for the current platform.
|
// addresses and information suitable for the current platform.
|
||||||
extern volatile mod_tmu_t TMU;
|
extern mod_tmu_t TMU;
|
||||||
|
|
||||||
#endif // _MODULES_TIMER
|
#endif // _MODULES_TIMER
|
||||||
|
|
|
@ -49,7 +49,7 @@ typedef enum
|
||||||
|
|
||||||
// Global MPU variable, accessible for direct tests. Initialized at the
|
// Global MPU variable, accessible for direct tests. Initialized at the
|
||||||
// beginning of execution.
|
// 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
|
// Quick SH3 test. It is safer to assume that an unknown model is SH4 because
|
||||||
// SH3-based models are not produced anymore.
|
// SH3-based models are not produced anymore.
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
//
|
//
|
||||||
// gint core module: rtc
|
// 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
|
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 is correct (use the time API for that).
|
||||||
*/
|
*/
|
||||||
rtc_time_t rtc_getTime(void);
|
void rtc_getTime(rtc_time_t *time);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
rtc_setTime()
|
rtc_setTime()
|
||||||
Sets the time in the RTC registers. The week day is set to 0 if greater
|
Sets the time in the RTC registers. The week day is set to 0 if greater
|
||||||
than 6. Other fields are not checked.
|
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
|
typedef enum
|
||||||
{
|
{
|
||||||
RTCFreq_500mHz = 7,
|
rtc_freq_500mHz = 7,
|
||||||
RTCFreq_1Hz = 6,
|
rtc_freq_1Hz = 6,
|
||||||
RTCFreq_2Hz = 5,
|
rtc_freq_2Hz = 5,
|
||||||
RTCFreq_4Hz = 4,
|
rtc_freq_4Hz = 4,
|
||||||
RTCFreq_16Hz = 3,
|
rtc_freq_16Hz = 3,
|
||||||
RTCFreq_64Hz = 2,
|
rtc_freq_64Hz = 2,
|
||||||
RTCFreq_256Hz = 1,
|
rtc_freq_256Hz = 1,
|
||||||
RTCFreq_None = 0,
|
rtc_freq_none = 0,
|
||||||
|
|
||||||
} rtc_frequency_t;
|
} rtc_frequency_t;
|
||||||
|
|
||||||
|
@ -94,7 +97,7 @@ void rtc_cb_end(int id);
|
||||||
-1 Callback does not exist
|
-1 Callback does not exist
|
||||||
-2 Invalid parameters
|
-2 Invalid parameters
|
||||||
This function never removes a callback. Call rtc_cb_end() for this. One
|
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.
|
temporarily disable the callback.
|
||||||
*/
|
*/
|
||||||
int rtc_cb_edit(int id, rtc_frequency_t new_freq, void (*new_function)(void));
|
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).
|
module display for more information on rectangle masks).
|
||||||
Which operation is performed is determined by the channel setting.
|
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];
|
operator &= c->masks[offset & 3];
|
||||||
|
|
||||||
switch(c->channel)
|
switch(c->channel)
|
||||||
{
|
{
|
||||||
case Channel_FullAlpha:
|
case channel_full_alpha:
|
||||||
bopti_vram[offset] &= ~operator;
|
bopti_vram[offset] &= ~operator;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Channel_Mono:
|
case channel_mono:
|
||||||
bopti_vram[offset] |= operator;
|
bopti_vram[offset] |= operator;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -30,31 +30,31 @@ void bopti_op_mono(int offset, uint32_t operator, struct Command *c)
|
||||||
break;
|
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];
|
operator &= c->masks[offset & 3];
|
||||||
|
|
||||||
switch(c->channel)
|
switch(c->channel)
|
||||||
{
|
{
|
||||||
case Channel_FullAlpha:
|
case channel_full_alpha:
|
||||||
bopti_v1[offset] &= ~operator;
|
bopti_v1[offset] &= ~operator;
|
||||||
bopti_v2[offset] &= ~operator;
|
bopti_v2[offset] &= ~operator;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Channel_LightAlpha:
|
case channel_light_alpha:
|
||||||
case Channel_DarkAlpha:
|
case channel_dark_alpha:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Channel_Mono:
|
case channel_mono:
|
||||||
bopti_v1[offset] |= operator;
|
bopti_v1[offset] |= operator;
|
||||||
bopti_v2[offset] |= operator;
|
bopti_v2[offset] |= operator;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Channel_Light:
|
case channel_light:
|
||||||
bopti_v1[offset] |= operator;
|
bopti_v1[offset] |= operator;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Channel_Dark:
|
case channel_dark:
|
||||||
bopti_v2[offset] |= operator;
|
bopti_v2[offset] |= operator;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ void bopti_op_gray(int offset, uint32_t operator, struct Command *c)
|
||||||
of 32, which is undefined behavior.
|
of 32, which is undefined behavior.
|
||||||
*/
|
*/
|
||||||
void bopti_grid_a32(const uint32_t *layer, int column_count, int height,
|
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_column_offset = (c->y << 2) + (c->x >> 5);
|
||||||
int vram_offset = vram_column_offset;
|
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,
|
void bopti_grid(const uint32_t *layer, int column_count, int height,
|
||||||
struct Command *c)
|
command_t *c)
|
||||||
{
|
{
|
||||||
if(!column_count) return;
|
if(!column_count) return;
|
||||||
if(!(c->x & 31))
|
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
|
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;
|
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) =
|
uint32_t (*get)(const unsigned char **data) =
|
||||||
(size == 2) ? bopti_end_get2 : bopti_end_get1;
|
(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 = (*get)(&end);
|
||||||
operator <<= shift;
|
operator <<= shift;
|
||||||
|
|
||||||
(c->op)(vram_offset, operator, c);
|
(c->op)(vram_offset, operator, c);
|
||||||
|
|
||||||
vram_offset += 4;
|
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) =
|
uint32_t (*get)(const unsigned char **data) =
|
||||||
(size == 2) ? (bopti_end_get2) : (bopti_end_get1);
|
(size == 2) ? (bopti_end_get2) : (bopti_end_get1);
|
||||||
|
|
||||||
int vram_offset = (c->y << 2) + (c->x >> 5);
|
int vram_offset = (c->y << 2) + (c->x >> 5);
|
||||||
uint32_t row_data, operator;
|
uint32_t row_data;
|
||||||
int row;
|
int row;
|
||||||
|
|
||||||
int shift_base = (32 - (size << 3));
|
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++)
|
for(row = c->top; row < c->bottom; row++)
|
||||||
{
|
{
|
||||||
row_data = (*get)(&end);
|
row_data = (*get)(&end);
|
||||||
|
(c->op)(vram_offset, row_data >> shift1, c);
|
||||||
operator = row_data >> shift1;
|
(c->op)(vram_offset + 1, row_data << shift2, c);
|
||||||
(c->op)(vram_offset, operator, c);
|
|
||||||
|
|
||||||
|
|
||||||
operator = row_data << shift2;
|
|
||||||
(c->op)(vram_offset + 1, operator, c);
|
|
||||||
|
|
||||||
|
|
||||||
vram_offset += 4;
|
vram_offset += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,7 +239,7 @@ void bopti_end(const unsigned char *end, int size, struct Command *c)
|
||||||
bopti()
|
bopti()
|
||||||
Draws a layer in the video ram.
|
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;
|
const unsigned char *grid, *end;
|
||||||
int grid_columns, has_end;
|
int grid_columns, has_end;
|
||||||
|
@ -283,9 +274,10 @@ void bopti(const unsigned char *layer, struct Structure *s, struct Command *c)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
getStructure()
|
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;
|
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;
|
if(!img || img->magic != 0x01) return;
|
||||||
|
|
||||||
struct Structure s;
|
structure_t s;
|
||||||
struct Command command;
|
command_t command;
|
||||||
int actual_width;
|
int actual_width;
|
||||||
int format = img->format, i = 0;
|
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);
|
getStructure(img, &s);
|
||||||
if(width < 0) width = s.width;
|
if(width < 0) width = s.width;
|
||||||
if(height < 0) height = s.height;
|
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;
|
if(!img || img->magic != 0x01) return;
|
||||||
|
|
||||||
struct Structure s;
|
structure_t s;
|
||||||
struct Command command;
|
command_t command;
|
||||||
int actual_width;
|
int actual_width;
|
||||||
int format = img->format, i = 0;
|
int format = img->format, i = 0;
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ void clock_measure(void)
|
||||||
{
|
{
|
||||||
htimer_7705 = htimer_setup(timer_user, 0xffffffff, timer_Po_4,
|
htimer_7705 = htimer_setup(timer_user, 0xffffffff, timer_Po_4,
|
||||||
1);
|
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
|
// 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)
|
static void clock_measure_7705(void)
|
||||||
{
|
{
|
||||||
timer_start(htimer_7705);
|
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
|
etext, btext, // Location of .text section
|
||||||
bdata, edata, // Location of .data section
|
bdata, edata, // Location of .data section
|
||||||
bbss, ebss, // Location of .bss 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
|
gint_vbr, // VBR address
|
||||||
romdata; // ROM address of .data section contents
|
romdata; // ROM address of .data section contents
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ __attribute__((section(".pretext.entry"))) int start(void)
|
||||||
{
|
{
|
||||||
#ifdef GINT_DIAGNOSTICS
|
#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.
|
// goes wrong we can try to analyze what's been going on.
|
||||||
volatile gint_diagnostics_t *dg = gint_diagnostics();
|
volatile gint_diagnostics_t *dg = gint_diagnostics();
|
||||||
|
|
||||||
|
@ -108,10 +108,11 @@ __attribute__((section(".pretext.entry"))) int start(void)
|
||||||
dg->stage = stage_mmu;
|
dg->stage = stage_mmu;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Detecting the MPU type, initializing the register module addresses,
|
// Initializing gint, which does several things:
|
||||||
// and initializing gint.
|
// - Detect the MPU and platform
|
||||||
mpu_init();
|
// - Initialize register addresses in a platform-independent way
|
||||||
mod_init();
|
// - Save the current environment information in a large buffer
|
||||||
|
// - Set up the interrupt handler and configure everything gint needs
|
||||||
gint_init();
|
gint_init();
|
||||||
|
|
||||||
#ifdef GINT_DIAGNOSTICS
|
#ifdef GINT_DIAGNOSTICS
|
||||||
|
@ -148,16 +149,15 @@ __attribute__((section(".pretext.entry"))) int start(void)
|
||||||
if(!x) exit_code = main();
|
if(!x) exit_code = main();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef GINT_DIAGNOSTICS
|
#ifdef GINT_DIAGNOSTICS
|
||||||
dg->stage = stage_leaving;
|
dg->stage = stage_leaving;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* TODO Flush and close opened streams. */
|
/* TODO Flush and close opened streams. */
|
||||||
|
|
||||||
// Calling exit handlers.
|
// Calling exit handlers and destructors.
|
||||||
while(atexit_index > 0) (*atexit_handlers[--atexit_index])();
|
while(atexit_index > 0) (*atexit_handlers[--atexit_index])();
|
||||||
|
|
||||||
// Calling the destructors.
|
|
||||||
fini();
|
fini();
|
||||||
|
|
||||||
#ifdef GINT_DIAGNOSTICS
|
#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 *vram = display_getCurrentVRAM();
|
||||||
uint32_t spc, ssr;
|
uint32_t spc, ssr;
|
||||||
__asm__("stc spc, %0" : "=rm"(spc));
|
__asm__("stc spc, %0" : "=r"(spc));
|
||||||
__asm__("stc ssr, %0" : "=rm"(ssr));
|
__asm__("stc ssr, %0" : "=r"(ssr));
|
||||||
|
|
||||||
dclear();
|
dclear();
|
||||||
text_configure(NULL, color_black);
|
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/gint.h>
|
||||||
#include <internals/interrupt_maps.h>
|
#include <internals/interrupt_maps.h>
|
||||||
#include <internals/exceptions.h>
|
#include <internals/exceptions.h>
|
||||||
|
@ -110,10 +101,10 @@ void gint_invoke(uint8_t type, uint8_t subtype)
|
||||||
uint16_t *pc;
|
uint16_t *pc;
|
||||||
|
|
||||||
// Getting some initial information to work with.
|
// Getting some initial information to work with.
|
||||||
__asm__("stc spc, %0" : "=rm"(pc));
|
__asm__("stc spc, %0" : "=r"(pc));
|
||||||
tea = gint_reg(register_tea);
|
tea = gint_reg(register_tea);
|
||||||
tra = gint_reg(register_tra);
|
tra = gint_reg(register_tra);
|
||||||
tcpr_2 = (void *)0xfffffeb8;
|
tcpr_2 = (void *)0xfffffeb8; /* SH7705 only */
|
||||||
|
|
||||||
// Building up the argument list.
|
// Building up the argument list.
|
||||||
for(int i = 0; i < 3; i++) switch(gint_handlers[type].args[i])
|
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/gint.h>
|
||||||
#include <internals/rtc.h>
|
#include <modules/timer.h>
|
||||||
|
#include <modules/rtc.h>
|
||||||
#include <gint.h>
|
#include <gint.h>
|
||||||
#include <timer.h>
|
#include <timer.h>
|
||||||
#include <7305.h>
|
#include <7305.h>
|
||||||
|
@ -38,31 +29,47 @@ volatile void *gint_reg_7305(gint_register_t reg)
|
||||||
|
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Setup.
|
// Register saves, setup, interrupt locks, register restoration.
|
||||||
//---
|
//---
|
||||||
|
|
||||||
static unsigned short ipr[12];
|
void gint_save_7305(environment_7305_t *e)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
// Saving the current interrupt priorities.
|
// Saving interrupt priorities.
|
||||||
ipr[0] = INTX.IPRA.WORD;
|
e->IPR[0] = INTX.IPRA.WORD;
|
||||||
ipr[1] = INTX.IPRB.WORD;
|
e->IPR[1] = INTX.IPRB.WORD;
|
||||||
ipr[2] = INTX.IPRC.WORD;
|
e->IPR[2] = INTX.IPRC.WORD;
|
||||||
ipr[3] = INTX.IPRD.WORD;
|
e->IPR[3] = INTX.IPRD.WORD;
|
||||||
ipr[4] = INTX.IPRE.WORD;
|
e->IPR[4] = INTX.IPRE.WORD;
|
||||||
ipr[5] = INTX.IPRF.WORD;
|
e->IPR[5] = INTX.IPRF.WORD;
|
||||||
ipr[6] = INTX.IPRG.WORD;
|
e->IPR[6] = INTX.IPRG.WORD;
|
||||||
ipr[7] = INTX.IPRH.WORD;
|
e->IPR[7] = INTX.IPRH.WORD;
|
||||||
ipr[8] = INTX.IPRI.WORD;
|
e->IPR[8] = INTX.IPRI.WORD;
|
||||||
ipr[9] = INTX.IPRJ.WORD;
|
e->IPR[9] = INTX.IPRJ.WORD;
|
||||||
ipr[10] = INTX.IPRK.WORD;
|
e->IPR[10] = INTX.IPRK.WORD;
|
||||||
ipr[11] = INTX.IPRL.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
|
// Disabling everything by default to avoid freezing on non-handled
|
||||||
// interrupts.
|
// interrupts.
|
||||||
INTX.IPRA.WORD = 0x0000;
|
INTX.IPRA.WORD = 0x0000;
|
||||||
|
@ -78,68 +85,52 @@ static void gint_priority_lock_7305(void)
|
||||||
INTX.IPRK.WORD = 0x0000;
|
INTX.IPRK.WORD = 0x0000;
|
||||||
INTX.IPRL.WORD = 0x0000;
|
INTX.IPRL.WORD = 0x0000;
|
||||||
|
|
||||||
// Saving keyboard registers.
|
// Allowing RTC and timer to schedule automatic tasks such as keyboard
|
||||||
inj1 = *((volatile unsigned short *)0xa4050116);
|
// analysis.
|
||||||
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.
|
|
||||||
INTX.IPRK._RTC = 10;
|
INTX.IPRK._RTC = 10;
|
||||||
INTX.IPRA.TMU0_0 = 12;
|
INTX.IPRA.TMU0_0 = 12;
|
||||||
INTX.IPRA.TMU0_1 = 12;
|
INTX.IPRA.TMU0_1 = 12;
|
||||||
INTX.IPRA.TMU0_2 = 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.
|
// Restoring the interrupt priorities.
|
||||||
INTX.IPRA.WORD = ipr[0];
|
INTX.IPRA.WORD = e->IPR[0];
|
||||||
INTX.IPRB.WORD = ipr[1];
|
INTX.IPRB.WORD = e->IPR[1];
|
||||||
INTX.IPRC.WORD = ipr[2];
|
INTX.IPRC.WORD = e->IPR[2];
|
||||||
INTX.IPRD.WORD = ipr[3];
|
INTX.IPRD.WORD = e->IPR[3];
|
||||||
INTX.IPRE.WORD = ipr[4];
|
INTX.IPRE.WORD = e->IPR[4];
|
||||||
INTX.IPRF.WORD = ipr[5];
|
INTX.IPRF.WORD = e->IPR[5];
|
||||||
INTX.IPRG.WORD = ipr[6];
|
INTX.IPRG.WORD = e->IPR[6];
|
||||||
INTX.IPRH.WORD = ipr[7];
|
INTX.IPRH.WORD = e->IPR[7];
|
||||||
INTX.IPRI.WORD = ipr[8];
|
INTX.IPRI.WORD = e->IPR[8];
|
||||||
INTX.IPRJ.WORD = ipr[9];
|
INTX.IPRJ.WORD = e->IPR[9];
|
||||||
INTX.IPRK.WORD = ipr[10];
|
INTX.IPRK.WORD = e->IPR[10];
|
||||||
INTX.IPRL.WORD = ipr[11];
|
INTX.IPRL.WORD = e->IPR[11];
|
||||||
|
|
||||||
// Restoring keyboard registers.
|
// Restoring RTC registers.
|
||||||
*((volatile unsigned short *)0xa4050116) = inj1;
|
RTC.RCR1->byte = e->RCR1;
|
||||||
*((volatile unsigned char *)0xa4050136) = data1;
|
RTC.RCR2->byte = e->RCR2;
|
||||||
*((volatile unsigned short *)0xa4050118) = inj2;
|
|
||||||
*((volatile unsigned char *)0xa4050138) = data2;
|
// Restoring TMU registers.
|
||||||
*((volatile unsigned short *)0xa405014c) = det;
|
*(TMU.timers[0]) = e->TMU0;
|
||||||
*((volatile unsigned char *)0xa405016c) = keys;
|
*(TMU.timers[1]) = e->TMU1;
|
||||||
*((volatile unsigned char *)0xa40501c6) = reg;
|
*(TMU.timers[2]) = e->TMU2;
|
||||||
}
|
TMU.TSTR->byte = e->TSTR;
|
||||||
|
|
||||||
void gint_setup_7305(void)
|
// Restoring keyboard-related I/O port registers. However the backlight
|
||||||
{
|
// pin is in PNDR and we would like the backlight to persist when we
|
||||||
volatile struct mod_rtc *RTC = RTC_SH7305;
|
// leave the application, so we just keep this bit.
|
||||||
|
*((volatile uint16_t *)0xa4050116) = e->PMCR;
|
||||||
gint_priority_lock_7305();
|
*((volatile uint8_t *)0xa4050136) = e->PMDR;
|
||||||
|
*((volatile uint16_t *)0xa4050118) = e->PNCR;
|
||||||
// Saving the RTC configuration.
|
*((volatile uint8_t *)0xa4050138) &= 0x10;
|
||||||
rcr2 = RTC->RCR2.BYTE;
|
*((volatile uint8_t *)0xa4050138) |= (e->PNDR & ~0x10);
|
||||||
// Disabling RTC interrupts by default.
|
*((volatile uint16_t *)0xa405014c) = e->PZCR;
|
||||||
RTC->RCR2.BYTE = 0x09;
|
*((volatile uint8_t *)0xa405016c) = e->PZDR;
|
||||||
}
|
*((volatile uint8_t *)0xa40501c6) = e->key;
|
||||||
|
|
||||||
void gint_stop_7305(void)
|
|
||||||
{
|
|
||||||
volatile struct mod_rtc *RTC = RTC_SH7305;
|
|
||||||
|
|
||||||
gint_priority_unlock_7305();
|
|
||||||
|
|
||||||
// Restoring the RTC configuration.
|
|
||||||
RTC->RCR2.BYTE = rcr2;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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/gint.h>
|
||||||
#include <internals/rtc.h>
|
#include <modules/rtc.h>
|
||||||
#include <gint.h>
|
#include <gint.h>
|
||||||
#include <timer.h>
|
#include <timer.h>
|
||||||
#include <7705.h>
|
#include <7705.h>
|
||||||
|
@ -38,24 +28,42 @@ volatile void *gint_reg_7705(gint_register_t reg)
|
||||||
|
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Setup.
|
// Register saves, setup, interrupt locks, register restoration.
|
||||||
//---
|
//---
|
||||||
|
|
||||||
static unsigned short iprs[8];
|
void gint_save_7705(environment_7705_t *e)
|
||||||
static unsigned char rcr2;
|
|
||||||
|
|
||||||
static void gint_priority_lock_7705(void)
|
|
||||||
{
|
{
|
||||||
// Saving the interrupt masks from registers IPRA to IPRH.
|
// Saving the interrupt masks from registers IPRA to IPRH.
|
||||||
iprs[0] = INTC.IPRA.WORD;
|
e->IPR[0] = INTC.IPRA.WORD;
|
||||||
iprs[1] = INTC.IPRB.WORD;
|
e->IPR[1] = INTC.IPRB.WORD;
|
||||||
iprs[2] = INTX.IPRC.WORD;
|
e->IPR[2] = INTX.IPRC.WORD;
|
||||||
iprs[3] = INTX.IPRD.WORD;
|
e->IPR[3] = INTX.IPRD.WORD;
|
||||||
iprs[4] = INTX.IPRE.WORD;
|
e->IPR[4] = INTX.IPRE.WORD;
|
||||||
iprs[5] = INTX.IPRF.WORD;
|
e->IPR[5] = INTX.IPRF.WORD;
|
||||||
iprs[6] = INTX.IPRG.WORD;
|
e->IPR[6] = INTX.IPRG.WORD;
|
||||||
iprs[7] = INTX.IPRH.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
|
// Disabling everything by default to avoid receiving an interrupt that
|
||||||
// the handler doesn't handle, which would cause the user program to
|
// the handler doesn't handle, which would cause the user program to
|
||||||
// freeze.
|
// freeze.
|
||||||
|
@ -68,44 +76,44 @@ static void gint_priority_lock_7705(void)
|
||||||
INTX.IPRG.WORD = 0x0000;
|
INTX.IPRG.WORD = 0x0000;
|
||||||
INTX.IPRH.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._RTC = 10;
|
||||||
INTC.IPRA.BIT._TMU0 = 12;
|
INTC.IPRA.BIT._TMU0 = 12;
|
||||||
INTC.IPRA.BIT._TMU1 = 12;
|
INTC.IPRA.BIT._TMU1 = 12;
|
||||||
INTC.IPRA.BIT._TMU2 = 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.
|
// Restoring the saved states.
|
||||||
INTC.IPRA.WORD = iprs[0];
|
INTC.IPRA.WORD = e->IPR[0];
|
||||||
INTC.IPRB.WORD = iprs[1];
|
INTC.IPRB.WORD = e->IPR[1];
|
||||||
INTX.IPRC.WORD = iprs[2];
|
INTX.IPRC.WORD = e->IPR[2];
|
||||||
INTX.IPRD.WORD = iprs[3];
|
INTX.IPRD.WORD = e->IPR[3];
|
||||||
INTX.IPRE.WORD = iprs[4];
|
INTX.IPRE.WORD = e->IPR[4];
|
||||||
INTX.IPRF.WORD = iprs[5];
|
INTX.IPRF.WORD = e->IPR[5];
|
||||||
INTX.IPRG.WORD = iprs[6];
|
INTX.IPRG.WORD = e->IPR[6];
|
||||||
INTX.IPRH.WORD = iprs[7];
|
INTX.IPRH.WORD = e->IPR[7];
|
||||||
}
|
|
||||||
|
// Restoring RTC registers.
|
||||||
void gint_setup_7705(void)
|
RTC.RCR1->byte = e->RCR1;
|
||||||
{
|
RTC.RCR2->byte = e->RCR2;
|
||||||
volatile struct mod_rtc *RTC = RTC_SH7705;
|
|
||||||
|
// Restoring TMU registers.
|
||||||
gint_priority_lock_7705();
|
*(TMU.timers[0]) = e->TMU0;
|
||||||
|
*(TMU.timers[1]) = e->TMU1;
|
||||||
// Saving the RTC configuration.
|
*(TMU.timers[2]) = e->TMU2;
|
||||||
rcr2 = RTC->RCR2.BYTE;
|
TMU.TSTR->byte = e->TSTR;
|
||||||
// Disabling RTC interrupts by default.
|
|
||||||
RTC->RCR2.BYTE = 0x09;
|
// Restoring keyboard-related I/O port registers.
|
||||||
}
|
PFC.PACR.WORD = e->PACR;
|
||||||
|
PA.DR.BYTE = e->PADR;
|
||||||
void gint_stop_7705(void)
|
PFC.PBCR.WORD = e->PBCR;
|
||||||
{
|
PB.DR.BYTE = e->PBDR;
|
||||||
volatile struct mod_rtc *RTC = RTC_SH7705;
|
PFC.PMCR.WORD = e->PMCR;
|
||||||
|
PM.DR.BYTE = e->PMDR;
|
||||||
gint_priority_unlock_7705();
|
|
||||||
|
|
||||||
// Restoring the RTC configuration.
|
|
||||||
RTC->RCR2.BYTE = rcr2;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ _gint_setvbr:
|
||||||
jsr @r5
|
jsr @r5
|
||||||
nop
|
nop
|
||||||
|
|
||||||
/* Activating interrupts again. */
|
/* Enabling interrupts again. */
|
||||||
mov.l sr_block, r0
|
mov.l sr_block, r0
|
||||||
not r0, r0
|
not r0, r0
|
||||||
stc sr, r3
|
stc sr, r3
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#include <internals/gint.h>
|
#include <internals/gint.h>
|
||||||
#include <internals/interrupt_maps.h>
|
#include <internals/interrupt_maps.h>
|
||||||
|
#include <internals/modules.h>
|
||||||
#include <gint.h>
|
#include <gint.h>
|
||||||
#include <mpu.h>
|
#include <mpu.h>
|
||||||
|
|
||||||
gint_info_t gint;
|
gint_info_t gint;
|
||||||
|
static environment_t env;
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Initialization routines
|
// Initialization routines
|
||||||
|
@ -16,10 +18,17 @@ gint_info_t gint;
|
||||||
*/
|
*/
|
||||||
static void setup(void)
|
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)
|
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.
|
// Linker script symbols -- gint.
|
||||||
extern uint32_t
|
extern uint32_t
|
||||||
gint_vbr,
|
gint_vbr,
|
||||||
|
@ -32,6 +41,9 @@ void gint_init(void)
|
||||||
// Loading the interrupt handler into the memory.
|
// Loading the interrupt handler into the memory.
|
||||||
while(ptr < &egint) *ptr++ = *src++;
|
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.
|
// Installing gint's default exception/interrupt handlers.
|
||||||
for(int i = 0; i < exc_type_max; i++)
|
for(int i = 0; i < exc_type_max; i++)
|
||||||
{
|
{
|
||||||
|
@ -59,7 +71,8 @@ void gint_init(void)
|
||||||
*/
|
*/
|
||||||
static void stop(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)
|
void gint_quit(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#include <modules/timer.h>
|
#include <modules/timer.h>
|
||||||
|
#include <modules/rtc.h>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <mpu.h>
|
#include <mpu.h>
|
||||||
|
|
||||||
|
@ -11,7 +13,8 @@
|
||||||
// confront to the hardware directly.
|
// 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.timers[2] = (void *)0xfffffeac;
|
||||||
TMU.TSTR = (void *)0xfffffe92;
|
TMU.TSTR = (void *)0xfffffe92;
|
||||||
TMU.TCPR2 = (void *)0xfffffeb8;
|
TMU.TCPR2 = (void *)0xfffffeb8;
|
||||||
|
|
||||||
|
RTC.RCR1 = (void *)0xfffffedc;
|
||||||
|
RTC.RCR2 = (void *)0xfffffede;
|
||||||
|
RTC.time = (void *)0xfffffec0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mod_init_7305(void)
|
static void mod_init_7305(void)
|
||||||
|
@ -35,6 +42,10 @@ static void mod_init_7305(void)
|
||||||
TMU.timers[2] = (void *)0xa4490020;
|
TMU.timers[2] = (void *)0xa4490020;
|
||||||
TMU.TSTR = (void *)0xa4490004;
|
TMU.TSTR = (void *)0xa4490004;
|
||||||
TMU.TCPR2 = NULL;
|
TMU.TCPR2 = NULL;
|
||||||
|
|
||||||
|
RTC.RCR1 = (void *)0xa413fedc;
|
||||||
|
RTC.RCR2 = (void *)0xa413fede;
|
||||||
|
RTC.time = (void *)0xa413fec0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#include <mpu.h>
|
#include <mpu.h>
|
||||||
|
|
||||||
mpu_t MPU_CURRENT;
|
const mpu_t MPU_CURRENT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
getMPU()
|
getMPU()
|
||||||
|
@ -67,14 +67,3 @@ mpu_t getMPU(void)
|
||||||
// By default, the MPU is unknown.
|
// By default, the MPU is unknown.
|
||||||
return mpu_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
|
many keys on the same column are pressed, other keys of the same column
|
||||||
may be triggered.
|
may be triggered.
|
||||||
|
|
||||||
|
(The following values do not apply to the latest tests, even if the
|
||||||
|
trend remains the same.)
|
||||||
- Less Bad key detection.
|
- Less Bad key detection.
|
||||||
- 8 Very few column effects. Most often, three keys may be pressed
|
- 8 Very few column effects. Most often, three keys may be pressed
|
||||||
simultaneously. However, [UP] has latencies and is globally not
|
simultaneously. However, [UP] has latencies and is globally not
|
||||||
|
@ -49,7 +51,8 @@ static void kdelay(void)
|
||||||
|
|
||||||
__asm__
|
__asm__
|
||||||
(
|
(
|
||||||
"nop\n\t"
|
r4(r4("nop\n\t"))
|
||||||
|
r4(r4("nop\n\t"))
|
||||||
);
|
);
|
||||||
|
|
||||||
#undef r4
|
#undef r4
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
#include <internals/rtc.h>
|
#include <internals/rtc.h>
|
||||||
|
#include <modules/rtc.h>
|
||||||
#include <rtc.h>
|
#include <rtc.h>
|
||||||
#include <mpu.h>
|
#include <mpu.h>
|
||||||
|
|
||||||
// Array holding callback informations.
|
// 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).
|
// Callback identifier (unique).
|
||||||
static int unique_id = 1;
|
static int unique_id = 1;
|
||||||
// Current RTC interrupt frequency.
|
// 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.
|
// 256-Hz tick count. This counter is stopped when no callback is registered.
|
||||||
static unsigned elapsed256 = 0;
|
static unsigned elapsed256 = 0;
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ static unsigned elapsed256 = 0;
|
||||||
*/
|
*/
|
||||||
static void rtc_cb_update(void)
|
static void rtc_cb_update(void)
|
||||||
{
|
{
|
||||||
rtc_frequency_t max = RTCFreq_None;
|
rtc_frequency_t max = rtc_freq_none;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
for(n = 0; n < RTC_CB_ARRAY_SIZE; n++) if(cb_array[n].id)
|
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;
|
if(rtc_freq == max) return;
|
||||||
rtc_freq = max;
|
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 rtc_cb_add(rtc_frequency_t freq, void (*function)(void), int repeats)
|
||||||
{
|
{
|
||||||
int n = 0;
|
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++;
|
while(n < RTC_CB_ARRAY_SIZE && cb_array[n].id) n++;
|
||||||
if(n >= RTC_CB_ARRAY_SIZE) return -1;
|
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;
|
if(n >= RTC_CB_ARRAY_SIZE) return;
|
||||||
|
|
||||||
cb_array[n].id = 0;
|
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].callback = NULL;
|
||||||
cb_array[n].repeats = 0;
|
cb_array[n].repeats = 0;
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ void rtc_cb_interrupt(void)
|
||||||
|
|
||||||
for(n = 0; n < RTC_CB_ARRAY_SIZE; n++)
|
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;
|
if(!cb->id || !cb->freq) continue;
|
||||||
|
|
||||||
// Only execute callback when the number of elapsed 256-Hz
|
// Only execute callback when the number of elapsed 256-Hz
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
#include <internals/rtc.h>
|
#include <internals/rtc.h>
|
||||||
|
#include <modules/rtc.h>
|
||||||
#include <rtc.h>
|
#include <rtc.h>
|
||||||
#include <mpu.h>
|
#include <mpu.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
integer()
|
integer8(), integer16() [static]
|
||||||
Converts a BCD value to an integer.
|
Converts a BCD value to an integer.
|
||||||
*/
|
*/
|
||||||
static int integer8(int bcd)
|
static int integer8(uint8_t bcd)
|
||||||
{
|
{
|
||||||
return (bcd & 0x0f) + 10 * (bcd >> 4);
|
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)
|
return (bcd & 0xf) + 10 * ((bcd >> 4) & 0xf) + 100 * ((bcd >> 8) & 0xf)
|
||||||
+ 1000 * (bcd >> 12);
|
+ 1000 * (bcd >> 12);
|
||||||
|
@ -19,26 +20,23 @@ static int integer16(int bcd)
|
||||||
/*
|
/*
|
||||||
rtc_getTime()
|
rtc_getTime()
|
||||||
Reads the current time from the RTC. There is no guarantee that the
|
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;
|
if(!time) return;
|
||||||
rtc_time_t time;
|
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
rtc->RCR1.CF = 0;
|
RTC.RCR1->CF = 0;
|
||||||
|
|
||||||
time.seconds = integer8(rtc->RSECCNT.BYTE);
|
time->seconds = integer8(RTC.time->RSECCNT.byte);
|
||||||
time.minutes = integer8(rtc->RMINCNT.BYTE);
|
time->minutes = integer8(RTC.time->RMINCNT.byte);
|
||||||
time.hours = integer8(rtc->RHRCNT.BYTE);
|
time->hours = integer8(RTC.time->RHRCNT .byte);
|
||||||
time.month_day = integer8(rtc->RDAYCNT.BYTE);
|
time->month_day = integer8(RTC.time->RDAYCNT.byte);
|
||||||
time.month = integer8(rtc->RMONCNT.BYTE);
|
time->month = integer8(RTC.time->RMONCNT.byte);
|
||||||
time.year = integer16(rtc->RYRCNT.WORD);
|
time->year = integer16(RTC.time->RYRCNT.word);
|
||||||
time.week_day = rtc->RWKCNT;
|
time->week_day = RTC.time->RWKCNT;
|
||||||
}
|
}
|
||||||
while(rtc->RCR1.CF != 0);
|
while(RTC.RCR1->CF != 0);
|
||||||
|
|
||||||
return time;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include <internals/rtc.h>
|
#include <internals/rtc.h>
|
||||||
|
#include <modules/rtc.h>
|
||||||
#include <rtc.h>
|
#include <rtc.h>
|
||||||
#include <mpu.h>
|
#include <mpu.h>
|
||||||
|
|
||||||
int rtc_carry_flag = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
rtc_periodic_interrupt()
|
rtc_periodic_interrupt()
|
||||||
Handles an RTC interrupt by calling the callback.
|
Handles an RTC interrupt by calling the callback.
|
||||||
|
@ -12,6 +11,5 @@ void rtc_periodic_interrupt(void)
|
||||||
{
|
{
|
||||||
rtc_cb_interrupt();
|
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 <internals/rtc.h>
|
||||||
|
#include <modules/rtc.h>
|
||||||
#include <rtc.h>
|
#include <rtc.h>
|
||||||
#include <mpu.h>
|
#include <mpu.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bcd()
|
bcd8(), bcd16() [static]
|
||||||
Converts an integer to a BCD value.
|
Converts an integer to a BCD value.
|
||||||
*/
|
*/
|
||||||
static int bcd8(int integer)
|
static uint8_t bcd8(int integer)
|
||||||
{
|
{
|
||||||
integer %= 100;
|
integer %= 100;
|
||||||
return ((integer / 10) << 4) | (integer % 10);
|
return ((integer / 10) << 4) | (integer % 10);
|
||||||
}
|
}
|
||||||
static int bcd16(int integer)
|
static uint16_t bcd16(int integer)
|
||||||
{
|
{
|
||||||
integer %= 10000;
|
integer %= 10000;
|
||||||
return (bcd8(integer / 100) << 8) | bcd8(integer % 100);
|
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
|
Sets the time in the RTC registers. The week day is set to 0 if greater
|
||||||
than 6. Other fields are not checked.
|
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;
|
if(!time) return;
|
||||||
int wday = (time.week_day < 7) ? (time.week_day) : (0);
|
int wday = (time->week_day < 7) ? (time->week_day) : (0);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
rtc->RCR1.CF = 0;
|
RTC.RCR1->CF = 0;
|
||||||
|
|
||||||
rtc->RSECCNT.BYTE = bcd8(time.seconds);
|
RTC.time->RSECCNT.byte = bcd8(time->seconds);
|
||||||
rtc->RMINCNT.BYTE = bcd8(time.minutes);
|
RTC.time->RMINCNT.byte = bcd8(time->minutes);
|
||||||
rtc->RHRCNT.BYTE = bcd8(time.hours);
|
RTC.time->RHRCNT .byte = bcd8(time->hours);
|
||||||
rtc->RDAYCNT.BYTE = bcd8(time.month_day);
|
RTC.time->RDAYCNT.byte = bcd8(time->month_day);
|
||||||
rtc->RMONCNT.BYTE = bcd8(time.month);
|
RTC.time->RMONCNT.byte = bcd8(time->month);
|
||||||
rtc->RYRCNT.WORD = bcd16(time.year);
|
RTC.time->RYRCNT .word = bcd16(time->year);
|
||||||
rtc->RWKCNT = wday;
|
RTC.time->RWKCNT = wday;
|
||||||
}
|
}
|
||||||
while(rtc->RCR1.CF != 0);
|
while(RTC.RCR1->CF != 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,11 @@
|
||||||
*/
|
*/
|
||||||
time_t time(time_t *timeptr)
|
time_t time(time_t *timeptr)
|
||||||
{
|
{
|
||||||
rtc_time_t rtc = rtc_getTime();
|
rtc_time_t rtc;
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
time_t calendar;
|
time_t calendar;
|
||||||
|
|
||||||
|
rtc_getTime(&rtc);
|
||||||
tm.tm_sec = rtc.seconds;
|
tm.tm_sec = rtc.seconds;
|
||||||
tm.tm_min = rtc.minutes;
|
tm.tm_min = rtc.minutes;
|
||||||
tm.tm_hour = rtc.hours;
|
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