Moved the keyboard to timers. Minor changes in multigetkey() to avoid unwanted event repeats. Beginning of a test application.

This commit is contained in:
lephe 2016-05-05 18:19:10 +02:00
parent 037382edb4
commit 9725c2819a
12 changed files with 320 additions and 141 deletions

8
TODO
View file

@ -1,7 +1,9 @@
- screen, display
- timer
- gray engine
- multi-getkey repeats (if possible, which doesn't seem likely)
- getkey() may unwantedly repeat a key if it was triggered for multigetkey()
- write and test gray engine
- full rtc driver (time)
- callbacks and complete user API
_ 7305.h
_ libc

View file

@ -3,11 +3,26 @@
#include <mpu.h>
#include <keyboard.h>
#include <display.h>
#include <timer.h>
extern unsigned int gint_vbr, bgint, egint, gint_data;
/*
A few procedures for displaying text in the system's vram.
*/
extern void __Print(const char *msg, int x, int y);
extern unsigned int gint_vbr, bgint, egint, gint_data;
#define print __Print
void print_clear(void)
{
char *empty_line = " ";
int i = 0;
while(i < 8) print(empty_line, 0, i++);
}
void print(const char *str, int x, int y)
{
__Print(str, x, y);
}
void print_hex(unsigned int n, int x, int y)
{
char ch[11] = "0x";
@ -19,7 +34,7 @@ void print_hex(unsigned int n, int x, int y)
n >>= 4;
}
ch[10] = 0;
print(ch, x, y);
__Print(ch, x, y);
}
void print_bin(unsigned char n, int x, int y)
{
@ -32,9 +47,8 @@ void print_bin(unsigned char n, int x, int y)
n >>= 1;
}
ch[8] = 0;
print(ch, x, y);
__Print(ch, x, y);
}
void print_hexa(unsigned int n, int digits, int x, int y)
{
char ch[20];
@ -47,29 +61,35 @@ void print_hexa(unsigned int n, int digits, int x, int y)
}
ch[digits] = 0;
print(ch, x, y);
__Print(ch, x, y);
}
// Don't forget to enable key state debugging in the interrupt handler.
/*
Keyboard tests.
*/
void keyboard_test(void)
{
const char *names[] = {
"MPU_Unkown",
"MPU_SH7337",
"MPU_SH7355",
"MPU_SH7305",
"MPU_SH7724",
"Error"
};
/*
print_bin(keyboard_state[0], 0, 2);
print_bin(keyboard_state[1], 0, 3);
print_bin(keyboard_state[2], 0, 4);
print_bin(keyboard_state[3], 0, 5);
print_bin(keyboard_state[4], 0, 6);
print_bin(keyboard_state[5], 9, 2);
print_bin(keyboard_state[6], 9, 3);
print_bin(keyboard_state[7], 9, 4);
print_bin(keyboard_state[8], 9, 5);
print_bin(keyboard_state[9], 9, 6);
*/
int x = 0;
char str[3];
int keys[4] = { 0 };
int i;
print(names[MPU_CURRENT < 5 ? MPU_CURRENT : 5], 0, 0);
print("gint size:", 0, 1);
print_hex(&egint - &bgint, 11, 1);
print_clear();
while(1)
{
@ -251,7 +271,7 @@ void btest_gint_icon(void)
}
*/
int main(void)
void bitmap_test(void)
{
extern Image binary_symbol_start;
extern Image binary_symbol2_start;
@ -307,5 +327,69 @@ int main(void)
dupdate();
while(getkey() != KEY_EXE);
}
void test(void)
{
static int x = 0;
x++;
print_hex(x, 0, 0);
}
int main_menu(void)
{
/*
Main menu.
*/
const char *mpu_names[] = {
"MPU_Unkown",
"MPU_SH7337",
"MPU_SH7355",
"MPU_SH7305",
"MPU_SH7724",
"MPU Error !"
};
int key;
print_clear();
print("gint test application", 0, 0);
print("---------------------", 0, 1);
print("[1] Keyboard test", 2, 3);
print("[2] Drawing test", 2, 4);
print("mpu type:", 0, 6);
print(mpu_names[MPU_CURRENT < 5 ? MPU_CURRENT : 5], 11, 6);
print("gint size:", 0, 7);
print_hex(&egint - &bgint, 11, 7);
while(1)
{
key = getkey();
if(key == KEY_EXIT) return 0;
if(key == KEY_1) return 1;
if(key == KEY_2) return 2;
}
return 0;
}
int main(void)
{
int app;
while(1)
{
app = main_menu();
if(!app) break;
if(app == 1) keyboard_test();
if(app == 2) bitmap_test();
}
return 0;
}

Binary file not shown.

View file

@ -22,6 +22,20 @@ unsigned int gint_getVBR(void);
*/
unsigned int gint_systemVBR(void);
/*
gint_setRTCCallback()
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 gint_setRTCCallback(void (*callback)(void), enum GintFrequency frequency);
/*
gint_getRTCCallback()
Returns the callback function. If frequency is non-NULL, it is set to
the current frequency value.
*/
void (*(gint_getRTCCallback)(void))(enum GintFrequency *frequency);
//---
@ -79,8 +93,8 @@ void gint(void) __attribute__((
section(".gint.int.entry"),
interrupt_handler
));
void gint_7705(void) __attribute__((section(".gint.int")));
void gint_7305(void) __attribute__((section(".gint.int")));
void gint_7705(void) __attribute__((section(".gint.int")));
void gint_7305(void) __attribute__((section(".gint.int")));
@ -89,8 +103,11 @@ void gint_7305(void) __attribute__((section(".gint.int")));
//---
#define GINT_INTP_WDT 4
#define GINT_INTP_RTC 9
#define GINT_INTP_RTC 12
#define GINT_INTP_GRAY 15
#define GINT_INTP_KEY 8
#define GINT_INTP_TIMER 10

View file

@ -83,42 +83,24 @@
// Keyboard configuration.
//---
/*
enum KeyboardFrequency
Describes the various frequencies available for the keyboard analysis.
Default frequency is 16 Hz (system frequency is about 40 Hz). Very few
applications will need to change this setting.
Be aware that you will miss key hits at low frequencies.
At high frequencies, you will lose important execution power. Some
loop-driven programs will freeze at 64 Hz because they will never
leave the interrupt handling routine. SH3 also have difficulties with
64 Hz.
*/
enum KeyboardFrequency {
KeyFreq_500mHz = 7,
KeyFreq_1Hz = 6,
KeyFreq_2Hz = 5,
KeyFreq_4Hz = 4,
KeyFreq_16Hz = 3,
KeyFreq_64Hz = 2,
KeyFreq_256Hz = 1,
};
/*
keyboard_setFrequency()
Sets the keyboard frequency. Does nothing when the argument is not a
valid KeyboardFrequency value.
Sets the keyboard frequency. The default frequency is 32 Hz. Very few
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.
@arg frequency
@arg frequency Frequency in Hz (1 Hz = 1 event / second).
*/
void keyboard_setFrequency(enum KeyboardFrequency frequency);
// Currently not implemented.
// void keyboard_setFrequency(int frequency);
/*
keyboard_setRepeatRate()
Sets the default repeat rate for key events. The unit for the argument
is the keyboard period.
For example at 16 Hz, values of (10, 2) will imitate the system
default.
is the keyboard period. For example at 32 Hz, values of (20, 4) will
imitate the system default.
Set to 0 to disable repetition. If first = 0, no repetition will be
allowed. If first != 0 and next = 0, only one repetition will be
allowed.
@ -170,6 +152,19 @@ enum GetkeyOpt
*/
int keylast(int *repeat_count);
/*
keystate()
Returns the address of the keyboard state array. The keyboard state
consists in 10 bytes, in which every key is represented as a bit.
The returned address is the original buffer address. You should avoid
editing the array. It wouldn't influence the behavior of the keyboard
functions, but the buffer data is very volatile. Therefore, data
written to the buffer could be replaced anytime.
@return 10-byte keyboard state buffer.
*/
volatile unsigned char *keystate(void);
/*
getkey()
Blocking function with auto-repeat and SHIFT modifying functionalities.
@ -251,4 +246,41 @@ int keychar(int key);
*/
enum KeyType keytype(int key);
//---
// Internal API.
// Reference here for documentation purposes only. Do not call.
//---
/*
keyboard_interrupt()
Notifies the keyboard module that an interrupt request has been issued,
and updates the keyboard state.
*/
void keyboard_interrupt(void) __attribute__((section(".gint.int")));
/*
keyboard_updateState()
Updates the keyboard state.
@arg state 10-byte state buffer.
*/
void keyboard_updateState_7705(volatile unsigned char *state)
__attribute__((section(".gint.int")));
void keyboard_updateState_7305(volatile unsigned char *state)
__attribute__((section(".gint.int")));
/*
keyboard_init()
Starts the keyboard timer.
*/
void keyboard_init(void) __attribute__((constructor));
/*
keyboard_quit()
Stops the keyboard timer.
*/
void keyboard_quit(void) __attribute__((destructor));
#endif // _KEYBOARD_H

View file

@ -13,9 +13,9 @@
#define TIMER_2 2
#define TIMER_TMU2 TIMER_2
// Timer function identifiers.
#define TIMER_GRAY TIMER_TMU0
#define TIMER_USER1 TIMER_TMU1
#define TIMER_USER2 TIMER_TMU2
#define TIMER_KEYBOARD TIMER_TMU0
#define TIMER_GRAY TIMER_TMU1
#define TIMER_USER TIMER_TMU2
// Timer prescalers.
#define TIMER_Po_4 0
@ -31,11 +31,12 @@
//---
/*
timer_set()
timer_start()
Configures and starts a timer.
@arg timer Timer identifier. Use only TIMER_USER1 and
TIMER_USER2.
@arg timer Timer name. Use only TIMER_USER. You may use
TIMER_GRAY, if you're not running the gray
engine.
@arg delay Delay before expiration, in clock counts.
@arg prescaler Clock prescaler value. Possible values are
TIMER_Po_4, TIMER_Po_16, TIMER_Po_64,
@ -43,7 +44,7 @@
@arg callback Callback function.
@arg repetitions Number of repetitions, 0 for infinite.
*/
void timer_set(int timer, int delay, int prescaler, void (*callback)(void),
void timer_start(int timer, int delay, int prescaler, void (*callback)(void),
int repetitions);
/*
@ -68,6 +69,6 @@ void timer_stop(int timer);
@timer Timer that generated the interrupt.
*/
void timer_interrupt(int timer);
void timer_interrupt(int timer) __attribute__((section(".gint.int")));
#endif // _TIMER_H

BIN
libc.a

Binary file not shown.

BIN
libgint.a

Binary file not shown.

View file

@ -1,17 +1,17 @@
#include <gint.h>
#include <timer.h>
#include <keyboard.h>
#include <7305.h>
extern void print_hex(unsigned int value, int x, int y);
extern void print_bin(unsigned char value, int x, int y);
//---
// Interrupt codes.
//---
#define IC_RTC_PRI 0xaa0
#define IC_KEYSC 0xbe0
#define IC_TMU0_TUNI0 0x400
#define IC_TMU0_TUNI1 0x420
#define IC_TMU0_TUNI2 0x440
@ -19,9 +19,6 @@ extern void print_bin(unsigned char value, int x, int y);
// Keyboard management.
//---
extern volatile unsigned char keyboard_state[10];
extern void keyboard_interrupt(void);
/*
kdelay()
Should sleep during a few milliseconds. Well...
@ -143,16 +140,14 @@ static int krow(int row)
}
/*
kstate()
keyboard_updateState()
Updates the keyboard state.
*/
static void kstate(void)
void keyboard_updateState_7305(volatile unsigned char *keyboard_state)
{
int i;
for(i = 0; i < 10; i++) keyboard_state[i] = krow(i);
keyboard_interrupt();
}
@ -169,23 +164,19 @@ void gint_7305(void)
switch(code)
{
case IC_RTC_PRI:
// Clearing the interrupt flag.
RTC.RCR2.PEF = 0;
// Updating the keyboard state.
kstate();
/*
print_bin(keyboard_state[0], 0, 2);
print_bin(keyboard_state[1], 0, 3);
print_bin(keyboard_state[2], 0, 4);
print_bin(keyboard_state[3], 0, 5);
print_bin(keyboard_state[4], 0, 6);
break;
print_bin(keyboard_state[5], 9, 2);
print_bin(keyboard_state[6], 9, 3);
print_bin(keyboard_state[7], 9, 4);
print_bin(keyboard_state[8], 9, 5);
print_bin(keyboard_state[9], 9, 6);
*/
case IC_TMU0_TUNI0:
timer_interrupt(TIMER_TMU0);
break;
case IC_TMU0_TUNI1:
timer_interrupt(TIMER_TMU1);
break;
case IC_TMU0_TUNI2:
timer_interrupt(TIMER_TMU2);
break;
}
}
@ -245,7 +236,10 @@ static void gint_priority_lock_7305(void)
// 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 = GINT_INTP_RTC;
INTX.IPRK._RTC = GINT_INTP_RTC;
INTX.IPRA.TMU0_0 = GINT_INTP_KEY;
INTX.IPRA.TMU0_1 = GINT_INTP_GRAY;
INTX.IPRA.TMU0_2 = GINT_INTP_TIMER;
}
static void gint_priority_unlock_7305(void)

View file

@ -1,17 +1,17 @@
#include <gint.h>
#include <timer.h>
#include <keyboard.h>
#include <7705.h>
extern void print_hex(unsigned int value, int x, int y);
extern void print_bin(unsigned char value, int x, int y);
//---
// Interrupt codes.
//---
#define IC_RTC_PRI 0x4a0
#define IC_PINT07 0x700
#define IC_TMU0_TUNI0 0x400
#define IC_TMU1_TUNI1 0x420
#define IC_TMU2_TUNI2 0x440
@ -19,12 +19,11 @@ extern void print_bin(unsigned char value, int x, int y);
// Keyboard management.
//---
extern volatile unsigned char keyboard_state[10];
extern void keyboard_interrupt(void);
/*
kdelay()
Low-level sleep using the watchdog.
Used to be a low-level sleep using the watchdog, as in the system. This
way seems ok at least, and it doesn't create column effects as for
SH7305.
*/
static void kdelay(void)
{
@ -39,7 +38,7 @@ static void kdelay(void)
#undef r4
/*
/* Watchdog version.
const int delay = 0xf4;
// Disabling the watchdog timer interrupt and resetting the
@ -64,7 +63,7 @@ static void kdelay(void)
// Enabling back the watchdog timer interrupt.
INTC.IPRB.BIT._WDT = GINT_INTP_WDT;
*/
*/
}
/*
@ -134,16 +133,14 @@ static int krow(int row)
}
/*
kstate()
keyboard_updateState()
Updates the keyboard state.
*/
static void kstate(void)
void keyboard_updateState_7705(volatile unsigned char *keyboard_state)
{
int i;
for(i = 0; i < 10; i++) keyboard_state[i] = krow(i);
keyboard_interrupt();
}
@ -160,23 +157,19 @@ void gint_7705(void)
switch(code)
{
case IC_RTC_PRI:
// Clearing the interrupt flag.
RTC.RCR2.BIT.PEF = 0;
// Updating the keyboard state.
kstate();
/*
print_bin(keyboard_state[0], 0, 2);
print_bin(keyboard_state[1], 0, 3);
print_bin(keyboard_state[2], 0, 4);
print_bin(keyboard_state[3], 0, 5);
print_bin(keyboard_state[4], 0, 6);
break;
print_bin(keyboard_state[5], 9, 2);
print_bin(keyboard_state[6], 9, 3);
print_bin(keyboard_state[7], 9, 4);
print_bin(keyboard_state[8], 9, 5);
print_bin(keyboard_state[9], 9, 6);
*/
case IC_TMU0_TUNI0:
timer_interrupt(TIMER_TMU0);
break;
case IC_TMU1_TUNI1:
timer_interrupt(TIMER_TMU1);
break;
case IC_TMU2_TUNI2:
timer_interrupt(TIMER_TMU2);
break;
}
}
@ -214,7 +207,10 @@ static void gint_priority_lock_7705(void)
INTX.IPRH.WORD = 0x0000;
// Allowing RTC, which handles keyboard.
INTC.IPRA.BIT._RTC = GINT_INTP_RTC;
INTC.IPRA.BIT._RTC = GINT_INTP_RTC;
INTC.IPRA.BIT._TMU0 = GINT_INTP_KEY;
INTC.IPRA.BIT._TMU1 = GINT_INTP_GRAY;
INTC.IPRA.BIT._TMU2 = GINT_INTP_TIMER;
}
static void gint_priority_unlock_7705(void)

View file

@ -1,14 +1,18 @@
#include <keyboard.h>
#include <timer.h>
#include <mpu.h>
//---
// Keyboard variables.
//---
volatile unsigned char keyboard_state[10] = { 0 };
// These ones get modified by interrupts.
static volatile unsigned char keyboard_state[10] = { 0 };
static volatile int interrupt_flag = 0;
// Key statistics.
static int repeat_first = 10, repeat_next = 2;
static int last_key = KEY_NONE, last_repeats = 0, last_events = 0;
static volatile int interrupt_flag = 0;
@ -18,9 +22,9 @@ static volatile int interrupt_flag = 0;
/*
sleep()
Puts the CPU in sleep mode and waits for an interrupt to return.
Puts the CPU to sleep and waits for an interrupt.
*/
void sleep(void)
static void sleep(void)
{
__asm__
(
@ -34,7 +38,7 @@ void sleep(void)
@return A pressed key.
*/
int getPressedKey(void)
static int getPressedKey(void)
{
int row = 1, column = 0;
int state;
@ -62,7 +66,7 @@ int getPressedKey(void)
@return Number of actual pressed keys found.
*/
int getPressedKeys(int *keys, int count)
static int getPressedKeys(int *keys, int count)
{
int row = 1, column;
int found = 0, actually_pressed;
@ -109,16 +113,46 @@ int getPressedKeys(int *keys, int count)
return actually_pressed;
}
//---
// Interrupt management.
//---
/*
keyboard_interrupt()
Callback for keyboard update. Allows keyboard analysis functions to
wake only when RTC interrupts happen.
wake only when keyboard interrupts happen.
*/
void keyboard_interrupt(void)
{
if(isSH3())
keyboard_updateState_7705(keyboard_state);
else
keyboard_updateState_7305(keyboard_state);
interrupt_flag = 1;
}
/*
keyboard_init()
Starts the keyboard timer.
*/
void keyboard_init(void)
{
timer_start(TIMER_KEYBOARD, 1700, TIMER_Po_256, keyboard_interrupt,
0);
}
/*
keyboard_quit()
Stops the keyboard timer.
*/
void keyboard_quit(void)
{
timer_stop(TIMER_KEYBOARD);
}
//---
@ -127,20 +161,12 @@ void keyboard_interrupt(void)
/*
keyboard_setFrequency()
Sets the keyboard frequency. Does nothing when the argument is not a
valid KeyboardFrequency value.
Sets the keyboard frequency.
@arg frequency
@arg frequency In Hz.
*/
void keyboard_setFrequency(enum KeyboardFrequency frequency)
void keyboard_setFrequency(int frequency)
{
volatile unsigned char *rcr2;
if(frequency < 1 || frequency > 7) return;
rcr2 = (unsigned char *)(isSH3() ? 0xfffffede : 0xa413fede);
frequency <<= 4;
*rcr2 = (*rcr2 & 0x8f) | frequency;
}
/*
@ -185,6 +211,21 @@ int keylast(int *repeat_count)
/*
keystate()
Returns the address of the keyboard state array. The returned address
if the handler's buffer, therefore it contains volatile data.
@return 10-byte keyboard state buffer.
*/
volatile unsigned char *keystate(void)
{
return keyboard_state;
}
/*
getkey()
Blocking function with auto-repeat and SHIFT modifying functionalities.
@ -330,6 +371,18 @@ void multigetkey(int *keys, int count, int max_cycles)
if(max_cycles > 0) max_cycles--;
number = getPressedKeys(keys, count);
// We need to update the last key data, in case multigetkey()
// returns a single key, and getkey() is called a short time
// after. Otherwise getkey() could re-send an event for this
// key.
if(number == 1)
{
last_key = keys[0];
last_repeats = 0;
last_events = 0;
}
if(number) return;
// Handle key repetitions.

View file

@ -77,7 +77,7 @@ void timer_get(int timer, struct mod_tmu **tmu, unsigned char **tstr)
}
/*
timer_set()
timer_start()
Configures and starts a timer.
@arg timer Timer identifier.
@ -86,7 +86,7 @@ void timer_get(int timer, struct mod_tmu **tmu, unsigned char **tstr)
@arg callback Callback function.
@arg repetitions Number of repetitions, 0 for infinite.
*/
void timer_set(int timer, int delay, int prescaler, void (*callback)(void),
void timer_start(int timer, int delay, int prescaler, void (*callback)(void),
int repetitions)
{
// Getting the timer address. Using a byte to alter TSTR.