Proper RTC callback system. Moved keyboard to RTC (saves a timer). Reduced use of 7705.h / 7305.h.

This commit is contained in:
lephe 2016-09-04 11:35:41 +02:00
parent d80de5683b
commit 98fdbbc333
26 changed files with 351 additions and 639 deletions

4
TODO
View file

@ -2,12 +2,11 @@ Bugs to fix:
- Left-vram overflow when rendering text
- A few key hits ignored after leaving the application (could not reproduce)
- Lost keyboard control at startup (could not reproduce)
- Back-light issues
- Back-light issues (0xa400012c on SH3, 0xa4050138 on SH4)
Simple improvements:
- bopti: Monochrome bitmaps blending modes
- bopti: Partial transparency
- clock: Compute clock frequencies
- demo: Try 284x124 at (-60, -28) (all disadvantages)
- display: Rectangle-based drawing functions
- tales: Test all font encodings
@ -19,6 +18,7 @@ Simple improvements:
Modules to implement:
- Serial communication
- Sound playback and synthesizing
- Handle errors within errno
Things to investigate:
- Packed bit fields alignment

View file

@ -288,7 +288,7 @@ void main_menu(int *category, int *app)
// Quite a few things to declare...
//---
extern Image res_opt_menu_start;
extern Image res_opt_menu;
const char *mpu, *mpu_names[] = {
"Unknown",
@ -374,7 +374,7 @@ void main_menu(int *category, int *app)
print(1, 1, "Tab %d", tab);
break;
}
dimage(0, 56, &res_opt_menu_start);
dimage(0, 56, &res_opt_menu);
if(list)
{

View file

@ -53,28 +53,28 @@ static void getxy(Image *img, int *x, int *y)
static Image *select(Image *current)
{
extern Image res_bopti_thumbs_start;
extern Image res_bopti_thumbs;
extern Image
res_items_start,
res_sprites_start,
res_swords_start,
res_zelda_start,
res_isometric_start;
res_items,
res_sprites,
res_swords,
res_zelda,
res_isometric;
struct {
Image *img;
const char *name;
const char *info;
} images[] = {
{ &res_items_start, "Items", "Gray" },
{ &res_sprites_start, "Sprites", "Gray" },
{ &res_swords_start, "Swords", "Gray Alpha" },
{ &res_zelda_start, "Zelda", "Mono" },
{ &res_isometric_start, "Isometric", "Mono Alpha" },
{ &res_items, "Items", "Gray" },
{ &res_sprites, "Sprites", "Gray" },
{ &res_swords, "Swords", "Gray Alpha" },
{ &res_zelda, "Zelda", "Mono" },
{ &res_isometric, "Isometric", "Mono Alpha" },
{ NULL, NULL, NULL }
};
Image *thumbs = &res_bopti_thumbs_start;
Image *thumbs = &res_bopti_thumbs;
int items = 0;
static int row = 0;
int leave = 1, i;
@ -134,7 +134,7 @@ static Image *select(Image *current)
void test_bopti(void)
{
extern Image res_opt_bitmap_start;
extern Image res_opt_bitmap;
Image *img = NULL;
int leave = 1;
@ -152,7 +152,7 @@ void test_bopti(void)
if(img) gimage(x, y, img);
gclear_area(0, 55, 127, 63);
gimage(0, 56, &res_opt_bitmap_start);
gimage(0, 56, &res_opt_bitmap);
gupdate();
}
else if(img)
@ -164,7 +164,7 @@ void test_bopti(void)
if(img) dimage(x, y, img);
dclear_area(0, 55, 127, 63);
dimage(0, 56, &res_opt_bitmap_start);
dimage(0, 56, &res_opt_bitmap);
dupdate();
}
else
@ -174,7 +174,7 @@ void test_bopti(void)
dclear();
locate(3, 3, "No image selected");
dimage(0, 56, &res_opt_bitmap_start);
dimage(0, 56, &res_opt_bitmap);
dupdate();
}

View file

@ -10,7 +10,7 @@
static void draw(int delay1, int delay2, int selected)
{
extern Image res_opt_gray_start;
extern Image res_opt_gray;
unsigned int *vl = gray_lightVRAM();
unsigned int *vd = gray_darkVRAM();
@ -36,7 +36,7 @@ static void draw(int delay1, int delay2, int selected)
locate(3, selected ? 6 : 4, "\x02");
gimage(0, 56, &res_opt_gray_start);
gimage(0, 56, &res_opt_gray);
gupdate();
}

View file

@ -18,7 +18,7 @@
static void draw(struct RTCTime time)
{
extern Image res_rtc_segments_start;
extern Image res_rtc_segments;
const char *days[7] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
@ -38,7 +38,7 @@ static void draw(struct RTCTime time)
digits[5] = time.seconds % 10;
// Drawing digits.
for(i = 0; i < 6; i++) dimage_part(x[i], 8, &res_rtc_segments_start,
for(i = 0; i < 6; i++) dimage_part(x[i], 8, &res_rtc_segments,
12 * digits[i], 0, 11, 19);
// Drawing ':' between pairs of digits.
for(i = 0; i < 16; i++) dpixel(47 + 32 * (i >= 8) + (i & 1),
@ -52,13 +52,13 @@ static void draw(struct RTCTime time)
static void callback(void)
{
extern Image res_opt_rtc_start;
extern Image res_opt_rtc;
struct RTCTime time = rtc_getTime();
time.year += 1900;
dclear();
draw(time);
dimage_part(0, 56, &res_opt_rtc_start, 0, 0, 19, 8);
dimage_part(0, 56, &res_opt_rtc, 0, 0, 19, 8);
dupdate();
}
@ -116,8 +116,8 @@ static void set_region(struct RTCTime *time, int region, int value)
static void set(void)
{
extern Image res_opt_rtc_start;
Image *opt = &res_opt_rtc_start;
extern Image res_opt_rtc;
Image *opt = &res_opt_rtc;
struct {
int x, y;
@ -239,9 +239,9 @@ static void set(void)
void test_rtc(void)
{
int key;
int key, cb_id;
rtc_setCallback(callback, RTCFreq_1Hz);
cb_id = rtc_cb_add(RTCFreq_1Hz, callback, 0);
callback();
while(1)
@ -250,13 +250,13 @@ void test_rtc(void)
if(key == KEY_EXIT) break;
if(key == KEY_F1)
{
rtc_setCallback(NULL, RTCFreq_1Hz);
{
rtc_cb_edit(cb_id, RTCFreq_None, NULL);
set();
callback();
rtc_setCallback(callback, RTCFreq_1Hz);
rtc_cb_edit(cb_id, RTCFreq_1Hz, callback);
}
}
rtc_setCallback(NULL, RTCFreq_1Hz);
rtc_cb_end(cb_id);
}

View file

@ -12,13 +12,13 @@
static Font *select(Font *current)
{
extern Font res_font_modern_start;
extern Font res_font_modern;
struct {
Font *font;
const char *name;
} fonts[] = {
{ NULL, "gint default" },
{ &res_font_modern_start, "Modern" },
{ NULL, "gint default" },
{ &res_font_modern, "Modern" },
};
int font_number = 2;
@ -82,7 +82,7 @@ void test_tales(void)
{
enum Color colors[] = { Color_Black, Color_Dark, Color_Light,
Color_White, Color_Invert };
extern Image res_opt_tales_start;
extern Image res_opt_tales;
Font *font = NULL;
int black_bg = 0;
@ -116,7 +116,7 @@ void test_tales(void)
gtext(2, 2 + i * height, str);
}
gimage(0, 56, &res_opt_tales_start);
gimage(0, 56, &res_opt_tales);
x = 45 + 8 * color;
gline(x, 57, x + 5, 57, Color_Black);

View file

@ -21,6 +21,7 @@ static struct ClockConfig conf;
static volatile int elapsed_timer = -1;
static volatile int elapsed_rtc = -1;
static int cb_id = -1;
static void timing_rtc(void)
{
@ -36,7 +37,7 @@ static void timing_start(void)
{
timer_start(TIMER_USER, clock_setting(16, Clock_Hz), TIMER_Po_4,
timing_timer, 0);
rtc_setCallback(timing_rtc, RTCFreq_16Hz);
rtc_cb_edit(cb_id, RTCFreq_16Hz, timing_rtc);
elapsed_timer = 0;
elapsed_rtc = 0;
@ -54,8 +55,8 @@ static void timing_start(void)
*/
static void small_text(int x, int y, const char *text, int alignment)
{
extern Image res_clock_chars_start;
Image *chars = &res_clock_chars_start;
extern Image res_clock_chars;
Image *chars = &res_clock_chars;
const char *table = "0123456789kMHz*/";
if(alignment) x -= 2 * strlen(text) - 1, y -= 2;
@ -75,27 +76,15 @@ static void small_text(int x, int y, const char *text, int alignment)
/*
getFreq()
Prints the given frequency in a string on the form:
332kHz
<-><->
3 3
There are 1, 2 or 3 characters for the value, and 2 or 3
characters for the unit. The string is compacted.
*/
void getFreq(char *str, int freq)
{
if(freq < 1000)
{
sprintf(str, "%dHz", freq);
return;
}
if(freq < 1000000)
{
sprintf(str, "%dkHz", (freq + 500) / 1000);
return;
}
sprintf(str, "%dMHz", (freq + 500000) / 1000000);
if(freq < 1000) sprintf(str, "%dHz", freq);
else if(freq < 1000000) sprintf(str, "%dkHz", (freq + 500) / 1000);
else sprintf(str, "%dMHz", (freq + 500000) / 1000000);
}
/*
@ -140,14 +129,14 @@ static void display_freq(int x, int y, int freq)
*/
static void draw(int tab)
{
extern Image res_opt_timer_start;
extern Image res_clock_7705_start;
extern Image res_clock_7305_start;
extern Image res_opt_timer;
extern Image res_clock_7705;
extern Image res_clock_7305;
char buffer[16];
dclear();
dimage(0, 56, &res_opt_timer_start);
dimage(0, 56, &res_opt_timer);
if(!tab)
{
@ -161,7 +150,7 @@ static void draw(int tab)
if(isSH3())
{
dimage(64, 0, &res_clock_7705_start);
dimage(64, 0, &res_clock_7705);
getFreq(buffer, conf.CKIO_f);
small_text(84, 16, buffer, 1);
@ -186,7 +175,7 @@ static void draw(int tab)
}
else
{
dimage(64, 0, &res_clock_7305_start);
dimage(64, 0, &res_clock_7305);
getFreq(buffer, conf.RTCCLK_f);
small_text(84, 14, buffer, 1);
@ -207,27 +196,26 @@ static void draw(int tab)
}
else
{
int timer = elapsed_timer, rtc = elapsed_rtc; // just in case
locate(1, 1, "Timer/RTC comparison");
locate(2, 3, "Timer");
if(elapsed_timer >= 0) print(12, 3, "%04x", elapsed_timer);
if(timer >= 0) print(12, 3, "%04x", timer);
else locate(12, 3, "...");
locate(2, 4, "RTC");
if(elapsed_rtc >= 0) print(12, 4, "%04x", elapsed_rtc);
if(rtc >= 0) print(12, 4, "%04x", rtc);
else locate(12, 4, "...");
// We define the accuracy of the timer as the square of the
// ratio between the two counters.
// We define the accuracy of the timer as the ratio between the
// two counters.
locate(2, 5, "Accuracy");
if(elapsed_rtc > 0 && elapsed_timer > 0)
if(rtc > 0 && timer > 0)
{
int ratio;
if(elapsed_timer <= elapsed_rtc)
ratio = (10000 * elapsed_timer) / elapsed_rtc;
else
ratio = (10000 * elapsed_rtc) / elapsed_timer;
ratio = (ratio * ratio) / 10000;
if(timer <= rtc) ratio = (10000 * timer) / rtc;
else ratio = (10000 * rtc) / timer;
print(12, 5, "%d.%02d %%", ratio / 100, ratio % 100);
}
@ -258,7 +246,7 @@ void test_timer(void)
elapsed_timer = -1;
elapsed_rtc = -1;
rtc_setCallback(timing_start, RTCFreq_16Hz);
cb_id = rtc_cb_add(RTCFreq_16Hz, timing_start, 0);
text_configure(NULL, Color_Black);
@ -270,7 +258,7 @@ void test_timer(void)
{
case KEY_EXIT:
timer_stop(TIMER_USER);
rtc_setCallback(NULL, RTCFreq_1Hz);
rtc_cb_end(cb_id);
return;
case KEY_F1:

View file

@ -12,194 +12,6 @@
#pragma pack(push, 1)
#define gap(n) unsigned: n << 3
//---
// Real-time clock.
//---
struct _st_rtc
{
unsigned char const R64CNT;
gap(1);
union {
unsigned char BYTE;
struct {
unsigned :1;
unsigned TENS :3;
unsigned ONES :4;
};
} RSECCNT;
gap(1);
union {
unsigned char BYTE;
struct {
unsigned :1;
unsigned TENS :3;
unsigned ONES :4;
};
} RMINCNT;
gap(1);
union {
unsigned char BYTE;
struct {
unsigned :2;
unsigned TENS :2;
unsigned ONES :4;
};
} RHRCNT;
gap(1);
// 0=Sunday, 1=Monday, ..., 6=Saturday, 7=Reserved (prohibited).
unsigned char RWKCNT;
gap(1);
union {
unsigned char BYTE;
struct {
unsigned :2;
unsigned TENS :2;
unsigned ONES :4;
};
} RDAYCNT;
gap(1);
union {
unsigned char BYTE;
struct {
unsigned :3;
unsigned TENS :1;
unsigned ONES :4;
};
} RMONCNT;
gap(1);
union {
unsigned short WORD;
struct {
unsigned THOUSANDS :4;
unsigned HUNDREDS :4;
unsigned TENS :4;
unsigned ONES :4;
};
} RYRCNT;
union {
unsigned char BYTE;
struct {
unsigned ENB :1;
unsigned TENS :3;
unsigned ONES :4;
};
} RSECAR;
gap(1);
union {
unsigned char BYTE;
struct {
unsigned ENB :1;
unsigned TENS :3;
unsigned ONES :4;
};
} RMINAR;
gap(1);
union {
unsigned char BYTE;
struct {
unsigned ENB :1;
unsigned :1;
unsigned TENS :2;
unsigned ONES :4;
};
} RHRAR;
gap(1);
union {
unsigned char BYTE;
struct {
unsigned ENB :1;
unsigned :4;
// See RTC.RDAYCNT for day encoding.
unsigned DAY :3;
};
} RWKAR;
gap(1);
union {
unsigned char BYTE;
struct {
unsigned ENB :1;
unsigned :1;
unsigned TENS :2;
unsigned ONES :4;
};
} RDAYAR;
gap(1);
union {
unsigned char BYTE;
struct {
unsigned ENB :1;
unsigned :2;
unsigned TENS :1;
unsigned ONES :4;
};
} RMONAR;
gap(1);
union {
unsigned char BYTE;
struct {
unsigned CF :1;
unsigned :2;
unsigned CIE :1;
unsigned AIE :1;
unsigned :2;
unsigned AF :1;
};
} RCR1;
gap(1);
union {
unsigned char BYTE;
struct {
unsigned PEF :1;
unsigned PES :3;
unsigned :1;
unsigned ADJ :1;
unsigned RESET :1;
unsigned START :1;
};
} RCR2;
gap(1);
union {
unsigned short WORD;
struct {
unsigned THOUSANDS :4;
unsigned HUNDREDS :4;
unsigned TENS :4;
unsigned ONES :4;
};
} RYRAR;
gap(2);
union {
unsigned char BYTE;
struct {
unsigned ENB :1;
unsigned :7;
};
} RCR3;
} __attribute__((packed));
//---
// Interrupt controller, part 1.
//---
@ -854,7 +666,6 @@ struct _st_intx
#define RTC (*(volatile struct _st_rtc *)0xa413fec0)
#define INTC (*(volatile struct _st_intc *)0xa4140000)
#define INTX (*(volatile struct _st_intx *)0xa4080000)

View file

@ -247,198 +247,6 @@ struct st_pn { /* struct PN */
} DR; /* */
}; /* */
struct st_rtc { /* struct RTC */
unsigned char R64CNT; /* R64CNT */
char wk1; /* */
union { /* RSECCNT */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char :1; /* */
unsigned char S10:3; /* 10sec */
unsigned char S1 :4; /* 1sec */
} BIT; /* */
} RSECCNT; /* */
char wk2; /* */
union { /* RMINCNT */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char :1; /* */
unsigned char M10:3; /* 10min */
unsigned char M1 :4; /* 1min */
} BIT; /* */
} RMINCNT; /* */
char wk3; /* */
union { /* RHRCNT */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char :2; /* */
unsigned char H10:2; /* 10sec */
unsigned char H1 :4; /* 1sec */
} BIT; /* */
} RHRCNT; /* */
char wk4; /* */
union { /* RWKCNT */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char :5; /* */
unsigned char WK:3; /* week */
} BIT; /* */
} RWKCNT; /* */
char wk5; /* */
union { /* RDAYCNT */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char :2; /* */
unsigned char D10:2; /* 10day */
unsigned char D1 :4; /* 1day */
} BIT; /* */
} RDAYCNT; /* */
char wk6; /* */
union { /* RMONCNT */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char :3; /* */
unsigned char M10:1; /* 10mon */
unsigned char M1 :4; /* 1mon */
} BIT; /* */
} RMONCNT; /* */
char wk7; /* */
union { /* RYRCNT */
unsigned short WORD; /* Word Access */
struct { /* Bit Access */
unsigned short Y1000:4; /* 1000year */
unsigned short Y100 :4; /* 100year */
unsigned short Y10 :4; /* 10year */
unsigned short Y1 :4; /* 1year */
} BIT; /* */
} RYRCNT; /* */
union { /* RSECAR */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char ENB:1; /* ENB */
unsigned char S10:3; /* 10sec */
unsigned char S1 :4; /* 1sec */
} BIT; /* */
} RSECAR; /* */
char wk8; /* */
union { /* RMINAR */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char ENB:1; /* ENB */
unsigned char M10:3; /* 10min */
unsigned char M1 :4; /* 1min */
} BIT; /* */
} RMINAR; /* */
char wk9; /* */
union { /* RHRAR */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char ENB:1; /* ENB */
unsigned char :1; /* */
unsigned char H10:2; /* 10sec */
unsigned char H1 :4; /* 1sec */
} BIT; /* */
} RHRAR; /* */
char wk10; /* */
union { /* RWKAR */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char ENB:1; /* ENB */
unsigned char :4; /* */
unsigned char WK :3; /* week */
} BIT; /* */
} RWKAR; /* */
char wk11; /* */
union { /* RDAYAR */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char ENB:1; /* ENB */
unsigned char :1; /* */
unsigned char D10:2; /* 10day */
unsigned char D1 :4; /* 1day */
} BIT; /* */
} RDAYAR; /* */
char wk12; /* */
union { /* RMONAR */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char ENB:1; /* ENB */
unsigned char :2; /* */
unsigned char M10:1; /* 10mon */
unsigned char M1 :4; /* 1mon */
} BIT; /* */
} RMONAR; /* */
char wk13; /* */
union { /* RCR1 */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char CF :1; /* CF */
unsigned char :2; /* */
unsigned char CIE:1; /* CIE */
unsigned char AIE:1; /* AIE */
unsigned char :2; /* */
unsigned char AF :1; /* AF */
} BIT; /* */
} RCR1; /* */
char wk14; /* */
union { /* RCR2 */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char PEF :1; /* PEF */
unsigned char PES :3; /* PES */
unsigned char RTCEN:1; /* RTCEN */
unsigned char ADJ :1; /* ADJ */
unsigned char RESET:1; /* RESET */
unsigned char START:1; /* START */
} BIT; /* */
} RCR2; /* */
};
struct st_tmu { /* struct TMU */
union { /* TSTR */
unsigned char BYTE; /* Byte Access */
struct { /* Bit Access */
unsigned char :5; /* */
unsigned char STR2:1; /* STR2 */
unsigned char STR1:1; /* STR1 */
unsigned char STR0:1; /* STR0 */
} BIT; /* */
} TSTR; /* */
}; /* */
struct st_tmu0 { /* struct TMU0 */
unsigned int TCOR; /* TCOR */
unsigned int TCNT; /* TCNT */
union { /* TCR */
unsigned short WORD; /* Word Access */
struct { /* Bit Access */
unsigned short :7; /* */
unsigned short UNF :1; /* UNF */
unsigned short :2; /* */
unsigned short UNIE:1; /* UNIE */
unsigned short CKEG:2; /* CKEG */
unsigned short TPSC:3; /* TPSC */
} BIT; /* */
} TCR; /* */
}; /* */
struct st_tmu2 { /* struct TMU2 */
unsigned int TCOR; /* TCOR */
unsigned int TCNT; /* TCNT */
union { /* TCR */
unsigned short WORD; /* Word Access */
struct {
unsigned short :6;
unsigned short ICPF:1;
unsigned short UNF :1;
unsigned short ICPE:2;
unsigned short UNIE:1;
unsigned short CKEG:2;
unsigned short TPSC:3;
} BIT;
} TCR;
char wk[2];
unsigned int TCPR;
};
struct st_usb { /* struct USB */
union { /* UCLKCR */
unsigned char BYTE; /* Byte Access */
@ -1262,7 +1070,6 @@ union un_stbcr2 {
#define CPG (*(volatile struct st_cpg *)0xffffff80)
#define WDT (*(volatile struct st_wdt *)0xffffff84)
#define RTC (*(volatile struct st_rtc *)0xfffffec0)
#define INTC (*(volatile struct st_intc *)0xfffffee0)
#define INTX (*(volatile struct st_intx *)0xa4000000)
#define PA (*(volatile struct st_pa *)0xa4000120)
@ -1279,10 +1086,6 @@ union un_stbcr2 {
#define SCP (*(volatile struct st_scp *)0xa4000136)
#define PM (*(volatile struct st_pm *)0xa4000138)
#define PN (*(volatile struct st_pn *)0xa400013a)
#define TMU (*(volatile struct st_tmu *)0xfffffe92)
#define TMU0 (*(volatile struct st_tmu0 *)0xfffffe94)
#define TMU1 (*(volatile struct st_tmu0 *)0xfffffea0)
#define TMU2 (*(volatile struct st_tmu2 *)0xfffffeac)
#define USB (*(volatile struct st_usb *)0xa40a0008)
#define SCIF0 (*(volatile struct st_scif *)0xa4400000)
#define SCIF2 (*(volatile struct st_scif *)0xa4410000)

View file

@ -7,6 +7,9 @@
//
//---
#ifndef _CLOCK_H
#define _CLOCK_H
//---
// Some type declarations.
//---
@ -121,3 +124,5 @@ void clock_measure(void);
Waits until the measurements are finished. This may be immediate.
*/
void clock_measure_end(void);
#endif // _CLOCK_H

View file

@ -11,6 +11,9 @@ extern volatile int interrupt_flag;
extern int repeat_first, repeat_next;
extern int last_key, last_repeats, last_events;
// RTC callback id.
extern unsigned cb_id;
/*
sleep()
Puts the CPU into sleep until an interrupt request is accepted.
@ -26,7 +29,9 @@ int getPressedKey(volatile unsigned char *keyboard_state);
/*
getPressedKeys()
Find 'count' pressed keys in the keyboard state and fills the 'keys'
array. Returns the number of actually-pressed keys found.
array. Returns the number of keys found.
WARNING: keyboard artifacts make this function read as pressed keys
that aren't (typically, LEFT + DOWN + SHIFT => ALPHA).
*/
int getPressedKeys(volatile unsigned char *keyboard_state, int *keys,
int count);

View file

@ -1,6 +1,27 @@
#ifndef _INTERNALS_RTC_H
#define _INTERNALS_RTC_H 1
#include <rtc.h>
#include <stddef.h>
#define RTC_CB_ARRAY_SIZE 5
/*
struct rtc_cb
An RTC callback.
*/
struct rtc_cb
{
enum RTCFrequency freq;
int id;
void (*callback)(void);
int repeats;
};
// The callback array.
struct rtc_cb cb_array[RTC_CB_ARRAY_SIZE];
/*
struct mod_rtc
This structure describes the arrangement of RTC register in the memory.

View file

@ -13,6 +13,8 @@
#ifndef _KEYBOARD_H
#define _KEYBOARD_H 1
#include <rtc.h>
//---
// Keycodes and related.
//---
@ -89,6 +91,21 @@
#define KEY_NONE 0x00
#define KEY_NOEVENT 0xff
/*
enum KeyboardFrequency
Possible values for the keyboard frequency.
*/
enum KeyboardFrequency
{
KeyboardFreq_500mHz = RTCFreq_500mHz,
KeyboardFreq_1Hz = RTCFreq_1Hz,
KeyboardFreq_2Hz = RTCFreq_2Hz,
KeyboardFreq_4Hz = RTCFreq_4Hz,
KeyboardFreq_16Hz = RTCFreq_16Hz,
KeyboardFreq_64Hz = RTCFreq_64Hz,
KeyboardFreq_256Hz = RTCFreq_256Hz,
};
//---
@ -97,15 +114,12 @@
/*
keyboard_setFrequency()
Sets the keyboard frequency. The default frequency is 32 Hz. The unit
for the argument is Hz. Very few applications will need to change this
setting.
The actual frequency is guaranteed to be greater than the argument.
Be aware that you will miss key hits at low frequencies. At higher
frequencies, you will lose important execution power.
Sets the keyboard frequency. The default frequency is 16 Hz. Very few
applications will need to change this setting.
At low frequencies, you will miss key hits. At high frequencies, you
may lose execution power.
*/
// Currently not implemented.
// void keyboard_setFrequency(int frequency);
void keyboard_setFrequency(enum KeyboardFrequency frequency);
/*
keyboard_setRepeatRate()

View file

@ -62,22 +62,39 @@ enum RTCFrequency
RTCFreq_16Hz = 3,
RTCFreq_64Hz = 2,
RTCFreq_256Hz = 1,
RTCFreq_None = 0,
};
/*
rtc_setCallback()
Sets the callback function for the real-time clock interrupt. If
frequency is non-zero, the clock frequency is set to the given value.
Set the callback to NULL to deactivate an existing callback.
rtc_cb_add()
Registers a new callback for the RTC. Returns the callback id on
success (positive integer), or one of the following error codes:
-1 Array is full
-2 Invalid parameter
The number of repeats may be set to 0, in which case the callback is
called indefinitely unless the user calls rtc_cb_end().
*/
void rtc_setCallback(void (*callback)(void), enum RTCFrequency frequency);
int rtc_cb_add(enum RTCFrequency freq, void (*function)(void), int repeats);
/*
rtc_getCallback()
Returns the callback function. If frequency is non-NULL, it is set to
the current frequency value.
rtc_cb_end()
Removes the callback with the given id (as returned by rtc_cb_add())
from the callback array.
*/
void (*rtc_getCallback(enum RTCFrequency *frequency))(void);
void rtc_cb_end(int id);
/*
rtc_cb_edit()
Changes information related to a callback. This function returns 0 on
success, or one of the following error codes:
-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
temporarily disable the callback.
*/
int rtc_cb_edit(int id, enum RTCFrequency new_freq,
void (*new_function)(void));
@ -95,17 +112,10 @@ void rtc_interrupt_7705(void) __attribute__((section(".gint.int")));
void rtc_interrupt_7305(void) __attribute__((section(".gint.int")));
/*
rtc_setFrequency()
Sets the RTC interrupt frequency and enables interrupts.
rtc_cb_interrupt()
Handles an RTC interrupt. Calls the RTC callbacks if necessary, and
updates the repeat counts.
*/
void rtc_setFrequency_7705(enum RTCFrequency frequency);
void rtc_setFrequency_7305(enum RTCFrequency frequency);
/*
rtc_getFrequency()
Returns the RTC interrupt frequency.
*/
enum RTCFrequency rtc_getFrequency_7705(void);
enum RTCFrequency rtc_getFrequency_7305(void);
void rtc_cb_interrupt(void);
#endif // _RTC_H

View file

@ -10,6 +10,8 @@
#ifndef _TIMER_H
#define _TIMER_H 1
#include <clock.h>
//---
// Constants.
//---

View file

@ -121,6 +121,7 @@ void sleep_us(int us_delay)
// Indicates whether the measurements are finished.
static volatile int clock_measure_done = 0;
// Once again SH7705 and SH7305 need different methods...
static int cb_id_7705 = -1;
static void clock_measure_7705();
static void clock_compute_7305();
@ -136,9 +137,8 @@ void clock_measure(void)
{
// We prepare the timer manually, without starting it, so that
// we only have to push the running bit to start it when the
// measurements begin. This might look of little effect but the
// timer configuration time (lost from the measurement) would
// make the precision no more than 97-98%.
// measurements begin. This might look of little effect but it
// makes the precision jump from ~97% to more than 99%.
volatile struct mod_tmu *tmu;
timer_get(TIMER_USER, &tmu, NULL);
@ -153,7 +153,7 @@ void clock_measure(void)
timers[TIMER_USER].callback = NULL;
timers[TIMER_USER].repeats = 0;
rtc_setCallback(clock_measure_7705, RTCFreq_256Hz);
cb_id_7705 = rtc_cb_add(RTCFreq_256Hz, clock_measure_7705, 0);
}
// On SH7305, assuming clock mode 3, we can compute the clock
@ -261,7 +261,7 @@ static void clock_measure_7705_finalize(int elapsed)
static void clock_measure_7705_callback(void)
{
timer_stop(TIMER_USER);
rtc_setCallback(NULL, RTCFreq_1Hz);
rtc_cb_end(cb_id_7705);
volatile struct mod_tmu *tmu;
timer_get(TIMER_USER, &tmu, NULL);
@ -284,5 +284,5 @@ static void clock_measure_7705(void)
timer_get(TIMER_USER, NULL, &tstr);
*tstr |= (1 << TIMER_USER);
rtc_setCallback(clock_measure_7705_callback, RTCFreq_256Hz);
rtc_cb_edit(cb_id_7705, RTCFreq_256Hz, clock_measure_7705_callback);
}

View file

@ -31,6 +31,12 @@ _free:
nop
1: .long 0xacc
_realloc:
mov.l syscall_table, r2
mov.l 1f, r0
jmp @r2
nop
1: .long 0xe6d
.align 4

View file

@ -1,18 +1,7 @@
#include <internals/keyboard.h>
#include <keyboard.h>
#include <clock.h>
#include <timer.h>
/*
keyboard_setFrequency()
Sets the keyboard frequency (in Hz).
*/
void keyboard_setFrequency(int frequency)
{
int setting = clock_setting(frequency, Clock_Hz);
if(setting <= 0) return;
timer_reload(TIMER_KEYBOARD, setting);
}
#include <rtc.h>
/*
keyboard_setRepeatRate()

View file

@ -17,6 +17,10 @@ volatile int interrupt_flag = 0;
int repeat_first = 10, repeat_next = 2;
int last_key = KEY_NONE, last_repeats = 0, last_events = 0;
// RTC callback id.
unsigned cb_id;
//---
// Interrupt management.
@ -43,8 +47,17 @@ void keyboard_interrupt(void)
*/
void keyboard_init(void)
{
int delay = clock_setting(16, Clock_Hz);
timer_start(TIMER_KEYBOARD, delay, TIMER_Po_4, keyboard_interrupt, 0);
cb_id = rtc_cb_add(RTCFreq_16Hz, keyboard_interrupt, 0);
}
/*
keyboard_setFrequency()
Sets the keyboard frequency.
*/
void keyboard_setFrequency(enum KeyboardFrequency frequency)
{
if(frequency < 1 || frequency > 7) return;
rtc_cb_edit(cb_id, frequency, keyboard_interrupt);
}
/*
@ -53,5 +66,5 @@ void keyboard_init(void)
*/
void keyboard_quit(void)
{
timer_stop(TIMER_KEYBOARD);
rtc_cb_end(cb_id);
}

View file

@ -9,6 +9,7 @@
//---
#include <internals/gint.h>
#include <internals/rtc.h>
#include <gint.h>
#include <timer.h>
#include <7305.h>
@ -194,18 +195,22 @@ static void gint_priority_unlock_7305(void)
void gint_setup_7305(void)
{
volatile struct mod_rtc *RTC = RTC_SH7305;
gint_priority_lock_7305();
// Saving the RTC configuration.
rcr2 = RTC.RCR2.BYTE;
rcr2 = RTC->RCR2.BYTE;
// Disabling RTC interrupts by default.
RTC.RCR2.BYTE = 0x09;
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;
RTC->RCR2.BYTE = rcr2;
}

View file

@ -9,6 +9,7 @@
//---
#include <internals/gint.h>
#include <internals/rtc.h>
#include <gint.h>
#include <timer.h>
#include <7705.h>
@ -165,18 +166,22 @@ static void gint_priority_unlock_7705(void)
void gint_setup_7705(void)
{
volatile struct mod_rtc *RTC = RTC_SH7705;
gint_priority_lock_7705();
// Saving the RTC configuration.
rcr2 = RTC.RCR2.BYTE;
rcr2 = RTC->RCR2.BYTE;
// Disabling RTC interrupts by default.
RTC.RCR2.BYTE = 0x09;
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;
RTC->RCR2.BYTE = rcr2;
}

View file

@ -1,34 +0,0 @@
#include <7305.h>
#include <rtc.h>
//---
// Various MPU-dependent procedures.
//---
/*
rtc_setFrequency()
Sets the RTC interrupt frequency and enables interrupts.
*/
void rtc_setFrequency_7305(enum RTCFrequency frequency)
{
if(frequency < 1 || frequency > 7) return;
RTC.RCR2.BYTE = (frequency << 4) | 0x09;
}
/*
rtc_getFrequency()
Returns the RTC interrupt frequency.
*/
enum RTCFrequency rtc_getFrequency_7305(void)
{
return (RTC.RCR2.BYTE & 0x70) >> 4;
}
/*
rtc_interrupt()
Handles an RTC interrupt by calling the callback.
*/
void rtc_interrupt_7305(void)
{
RTC.RCR2.PEF = 0;
}

View file

@ -1,34 +0,0 @@
#include <7705.h>
#include <rtc.h>
//---
// Various MPU-dependent procedures.
//---
/*
rtc_setFrequency()
Sets the RTC interrupt frequency and enables interrupts.
*/
void rtc_setFrequency_7705(enum RTCFrequency frequency)
{
if(frequency < 1 || frequency > 7) return;
RTC.RCR2.BYTE = (frequency << 4) | 0x09;
}
/*
rtc_getFrequency()
Returns the RTC interrupt frequency.
*/
enum RTCFrequency rtc_getFrequency_7705(void)
{
return (RTC.RCR2.BYTE & 0x70) >> 4;
}
/*
rtc_interrupt()
Handles an RTC interrupt by calling the callback.
*/
void rtc_interrupt_7705(void)
{
RTC.RCR2.BIT.PEF = 0;
}

151
src/rtc/rtc_callback.c Normal file
View file

@ -0,0 +1,151 @@
#include <internals/rtc.h>
#include <rtc.h>
#include <mpu.h>
// Array holding callback informations.
struct rtc_cb cb_array[RTC_CB_ARRAY_SIZE] = { 0 };
// Callback identifier (unique).
static int unique_id = 1;
// Current RTC interrupt frequency.
static enum RTCFrequency rtc_freq = RTCFreq_None;
// 256-Hz tick count. This counter is stopped when no callback is registered.
static unsigned elapsed256 = 0;
/*
rtc_cb_update()
After successful registration or deletion of a callback, updates the
RTC interrupt frequency stored in register RCR2. After update, the
interrupt frequency is high enough to handle all callbacks, but nothing
more (so that no time is wasted handling interrupts that occur too
often).
*/
static void rtc_cb_update(void)
{
enum RTCFrequency max = RTCFreq_None;
int n;
for(n = 0; n < RTC_CB_ARRAY_SIZE; n++) if(cb_array[n].id)
{
if(!max || (cb_array[n].freq && cb_array[n].freq < max))
max = cb_array[n].freq;
}
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_cb_add()
Registers a new callback for the RTC. Returns the callback id on
success (positive integer), or one of the following error codes:
-1 Array is full
-2 Invalid parameter
The number of repeats may be set to 0, in which case the callback is
called indefinitely unless the user calls rtc_cb_end().
*/
int rtc_cb_add(enum RTCFrequency freq, void (*function)(void), int repeats)
{
int n = 0;
if(freq == RTCFreq_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;
cb_array[n].freq = freq;
cb_array[n].callback = function;
cb_array[n].repeats = repeats;
cb_array[n].id = unique_id++;
rtc_cb_update();
return cb_array[n].id;
}
/*
rtc_cb_end()
Removes the callback with the given id (as returned by rtc_cb_add())
from the callback array.
*/
void rtc_cb_end(int id)
{
int n = 0;
while(n < RTC_CB_ARRAY_SIZE && cb_array[n].id != id) n++;
if(n >= RTC_CB_ARRAY_SIZE) return;
cb_array[n].id = 0;
cb_array[n].freq = RTCFreq_None;
cb_array[n].callback = NULL;
cb_array[n].repeats = 0;
rtc_cb_update();
}
/*
rtc_cb_edit()
Changes information related to a callback. This function returns 0 on
success, or one of the following error codes:
-1 Callback does not exist
-2 Invalid parameters
This function never removes a callback. Call rtc_cb_end() for this.
*/
int rtc_cb_edit(int id, enum RTCFrequency new_freq,
void (*new_function)(void))
{
if(new_freq < 0 || new_freq > 7) return -2;
int n = 0;
while(n < RTC_CB_ARRAY_SIZE && cb_array[n].id != id) n++;
if(n >= RTC_CB_ARRAY_SIZE) return -1;
cb_array[n].freq = new_freq;
cb_array[n].callback = new_function;
rtc_cb_update();
return 0;
}
/*
rtc_cb_interrupt()
Handles an RTC interrupt. Calls the RTC callbacks if necessary, and
updates the repeat counts.
*/
void rtc_cb_interrupt(void)
{
int n;
int scales[] = {
1, // 256 Hz
4, // 64 Hz
16, // 16 Hz
64, // 4 Hz
128, // 2 Hz
256, // 1 Hz
512, // 0.5 Hz
};
// Adding to elapsed256 the number of 256-Hz ticks that correspond to
// the current interrupt frequency, and rounding the result to a
// multiple of this tick number.
elapsed256 = (elapsed256 + scales[rtc_freq]) & ~(scales[rtc_freq] - 1);
for(n = 0; n < RTC_CB_ARRAY_SIZE; n++)
{
struct rtc_cb *cb = &cb_array[n];
if(!cb->id || !cb->freq) continue;
// Only execute callback when the number of elapsed 256-Hz
// ticks reach a multiple that correspond to the callback
// frequency.
if(elapsed256 & (scales[cb->freq] - 1)) continue;
if(cb->callback) (*cb->callback)();
if(cb->repeats)
{
if(cb->repeats == 1) rtc_cb_end(cb->id);
else cb->repeats--;
}
}
}

View file

@ -1,63 +1,15 @@
#include <internals/rtc.h>
#include <rtc.h>
#include <mpu.h>
#include <stddef.h>
static void (*rtc_callback)(void) = NULL;
//---
// Callback API.
//---
/*
rtc_setCallback()
Sets the callback function for the real-time clock interrupt. If
frequency is non-NULL, the clock frequency is set to the given value.
*/
void rtc_setCallback(void (*callback)(void), enum RTCFrequency frequency)
{
rtc_callback = callback;
if(frequency < 1 || frequency > 7) return;
if(isSH3())
rtc_setFrequency_7705(frequency);
else
rtc_setFrequency_7305(frequency);
}
/*
rtc_getCallback()
Returns the callback function. If frequency is non-NULL, it is set to
the current frequency value.
*/
void (*rtc_getCallback(enum RTCFrequency *frequency))(void)
{
if(!frequency) return rtc_callback;
if(isSH3())
*frequency = rtc_getFrequency_7705();
else
*frequency = rtc_getFrequency_7305();
return rtc_callback;
}
//---
// Interrupt management.
//---
/*
rtc_interrupt()
Handles an RTC interrupt by calling the callback.
*/
void rtc_interrupt(void)
{
if(rtc_callback) (*rtc_callback)();
rtc_cb_interrupt();
if(isSH3())
rtc_interrupt_7705();
else
rtc_interrupt_7305();
volatile struct mod_rtc *RTC = isSH3() ? RTC_SH7705 : RTC_SH7305;
RTC->RCR2.PEF = 0;
}

View file

@ -7,9 +7,9 @@
*/
void text_configure(struct Font *next_font, enum Color next_color)
{
extern Font gint_font_system_start;
extern Font gint_font_system;
if(next_font) font = next_font;
else font = &gint_font_system_start;
else font = &gint_font_system;
color = next_color;
}