From 98fdbbc333dff33f7ac725ea3765f6c4c2ec58bd Mon Sep 17 00:00:00 2001 From: lephe Date: Sun, 4 Sep 2016 11:35:41 +0200 Subject: [PATCH] Proper RTC callback system. Moved keyboard to RTC (saves a timer). Reduced use of 7705.h / 7305.h. --- TODO | 4 +- demo/gintdemo.c | 4 +- demo/test_bopti.c | 32 ++--- demo/test_gray.c | 4 +- demo/test_rtc.c | 24 ++-- demo/test_tales.c | 10 +- demo/test_timer.c | 60 ++++----- include/7305.h | 189 ---------------------------- include/7705.h | 197 ------------------------------ include/clock.h | 5 + include/internals/keyboard.h | 7 +- include/internals/rtc.h | 21 ++++ include/keyboard.h | 30 +++-- include/rtc.h | 50 +++++--- include/timer.h | 2 + src/clock/clock.c | 12 +- src/core/syscalls.s | 6 + src/keyboard/keyboard_config.c | 13 +- src/keyboard/keyboard_interrupt.c | 19 ++- src/mpu/gint_sh7305.c | 11 +- src/mpu/gint_sh7705.c | 11 +- src/mpu/rtc_7305.c | 34 ------ src/mpu/rtc_7705.c | 34 ------ src/rtc/rtc_callback.c | 151 +++++++++++++++++++++++ src/rtc/rtc_interrupt.c | 56 +-------- src/tales/tales_configuration.c | 4 +- 26 files changed, 351 insertions(+), 639 deletions(-) delete mode 100644 src/mpu/rtc_7305.c delete mode 100644 src/mpu/rtc_7705.c create mode 100644 src/rtc/rtc_callback.c diff --git a/TODO b/TODO index 39e6d9e..2e57e3f 100644 --- a/TODO +++ b/TODO @@ -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 diff --git a/demo/gintdemo.c b/demo/gintdemo.c index 32bba87..7284c35 100644 --- a/demo/gintdemo.c +++ b/demo/gintdemo.c @@ -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) { diff --git a/demo/test_bopti.c b/demo/test_bopti.c index 57695d5..7942f39 100644 --- a/demo/test_bopti.c +++ b/demo/test_bopti.c @@ -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(); } diff --git a/demo/test_gray.c b/demo/test_gray.c index 61d06aa..b562f1f 100644 --- a/demo/test_gray.c +++ b/demo/test_gray.c @@ -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(); } diff --git a/demo/test_rtc.c b/demo/test_rtc.c index e3c0a09..2264f00 100644 --- a/demo/test_rtc.c +++ b/demo/test_rtc.c @@ -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); } diff --git a/demo/test_tales.c b/demo/test_tales.c index 5a94190..644fc23 100644 --- a/demo/test_tales.c +++ b/demo/test_tales.c @@ -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); diff --git a/demo/test_timer.c b/demo/test_timer.c index 9191508..36ca64d 100644 --- a/demo/test_timer.c +++ b/demo/test_timer.c @@ -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: diff --git a/include/7305.h b/include/7305.h index 3288678..a34420f 100644 --- a/include/7305.h +++ b/include/7305.h @@ -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) diff --git a/include/7705.h b/include/7705.h index e5e934c..3282d34 100644 --- a/include/7705.h +++ b/include/7705.h @@ -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) diff --git a/include/clock.h b/include/clock.h index 744d341..58e5c30 100644 --- a/include/clock.h +++ b/include/clock.h @@ -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 diff --git a/include/internals/keyboard.h b/include/internals/keyboard.h index 3524f60..75f67fc 100644 --- a/include/internals/keyboard.h +++ b/include/internals/keyboard.h @@ -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); diff --git a/include/internals/rtc.h b/include/internals/rtc.h index 8449e58..43ccc94 100644 --- a/include/internals/rtc.h +++ b/include/internals/rtc.h @@ -1,6 +1,27 @@ #ifndef _INTERNALS_RTC_H #define _INTERNALS_RTC_H 1 +#include +#include + +#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. diff --git a/include/keyboard.h b/include/keyboard.h index a3cf2c8..ad1086a 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -13,6 +13,8 @@ #ifndef _KEYBOARD_H #define _KEYBOARD_H 1 +#include + //--- // 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() diff --git a/include/rtc.h b/include/rtc.h index 08d9880..805c91d 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -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 diff --git a/include/timer.h b/include/timer.h index 1a58e53..f896c4a 100644 --- a/include/timer.h +++ b/include/timer.h @@ -10,6 +10,8 @@ #ifndef _TIMER_H #define _TIMER_H 1 +#include + //--- // Constants. //--- diff --git a/src/clock/clock.c b/src/clock/clock.c index b785a07..f6a54f2 100644 --- a/src/clock/clock.c +++ b/src/clock/clock.c @@ -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); } diff --git a/src/core/syscalls.s b/src/core/syscalls.s index ffe3a43..55aa0ba 100644 --- a/src/core/syscalls.s +++ b/src/core/syscalls.s @@ -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 diff --git a/src/keyboard/keyboard_config.c b/src/keyboard/keyboard_config.c index f657479..e19347f 100644 --- a/src/keyboard/keyboard_config.c +++ b/src/keyboard/keyboard_config.c @@ -1,18 +1,7 @@ #include #include #include -#include - -/* - 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 /* keyboard_setRepeatRate() diff --git a/src/keyboard/keyboard_interrupt.c b/src/keyboard/keyboard_interrupt.c index c75c542..c5d103b 100644 --- a/src/keyboard/keyboard_interrupt.c +++ b/src/keyboard/keyboard_interrupt.c @@ -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); } diff --git a/src/mpu/gint_sh7305.c b/src/mpu/gint_sh7305.c index 5a27924..963fb32 100644 --- a/src/mpu/gint_sh7305.c +++ b/src/mpu/gint_sh7305.c @@ -9,6 +9,7 @@ //--- #include +#include #include #include #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; } diff --git a/src/mpu/gint_sh7705.c b/src/mpu/gint_sh7705.c index 61a0e2e..a11f5fa 100644 --- a/src/mpu/gint_sh7705.c +++ b/src/mpu/gint_sh7705.c @@ -9,6 +9,7 @@ //--- #include +#include #include #include #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; } diff --git a/src/mpu/rtc_7305.c b/src/mpu/rtc_7305.c deleted file mode 100644 index 89d8cbd..0000000 --- a/src/mpu/rtc_7305.c +++ /dev/null @@ -1,34 +0,0 @@ -#include <7305.h> -#include - -//--- -// 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; -} diff --git a/src/mpu/rtc_7705.c b/src/mpu/rtc_7705.c deleted file mode 100644 index b677bc2..0000000 --- a/src/mpu/rtc_7705.c +++ /dev/null @@ -1,34 +0,0 @@ -#include <7705.h> -#include - -//--- -// 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; -} diff --git a/src/rtc/rtc_callback.c b/src/rtc/rtc_callback.c new file mode 100644 index 0000000..3a69a95 --- /dev/null +++ b/src/rtc/rtc_callback.c @@ -0,0 +1,151 @@ +#include +#include +#include + +// 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--; + } + } +} diff --git a/src/rtc/rtc_interrupt.c b/src/rtc/rtc_interrupt.c index 96e66a3..775a220 100644 --- a/src/rtc/rtc_interrupt.c +++ b/src/rtc/rtc_interrupt.c @@ -1,63 +1,15 @@ +#include #include #include -#include - -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; } diff --git a/src/tales/tales_configuration.c b/src/tales/tales_configuration.c index 916b761..8b00345 100644 --- a/src/tales/tales_configuration.c +++ b/src/tales/tales_configuration.c @@ -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; }