Displayed keyboard state in test [1]. Implemented some API for user RTC interrupt management.

This commit is contained in:
lephe 2016-05-05 22:33:15 +02:00
parent 9725c2819a
commit e1a51dae21
18 changed files with 301 additions and 79 deletions

4
TODO
View file

@ -1,9 +1,11 @@
- multi-getkey repeats (if possible, which doesn't seem likely) - 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 - write and test gray engine
- full rtc driver (time) - full rtc driver (time)
- callbacks and complete user API - callbacks and complete user API
- exhaustive save for setjmp()
- registers that need to be saved when configuring gint
_ 7305.h _ 7305.h
_ libc _ libc

View file

@ -17,7 +17,7 @@ void print_clear(void)
{ {
char *empty_line = " "; char *empty_line = " ";
int i = 0; int i = 0;
while(i < 8) print(empty_line, 0, i++); while(i < 8) __Print(empty_line, 0, i++);
} }
void print(const char *str, int x, int y) void print(const char *str, int x, int y)
{ {
@ -66,30 +66,38 @@ void print_hexa(unsigned int n, int digits, int x, int y)
/* /*
Keyboard tests. Keyboard tests.
The user timer reproduces the parameters of the keyboard timer.
*/ */
void keyboard_test_timer(void)
{
volatile unsigned char *state = keystate();
print_bin(state[0], 0, 1);
print_bin(state[1], 0, 2);
print_bin(state[2], 0, 3);
print_bin(state[3], 0, 4);
print_bin(state[4], 0, 5);
print_bin(state[5], 9, 1);
print_bin(state[6], 9, 2);
print_bin(state[7], 9, 3);
print_bin(state[8], 9, 4);
print_bin(state[9], 9, 5);
}
void keyboard_test(void) void keyboard_test(void)
{ {
/*
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; int x = 0;
char str[3]; char str[3];
int keys[4] = { 0 }; int keys[4] = { 0 };
int i; int i;
timer_start(TIMER_USER, 1700, TIMER_Po_256, keyboard_test_timer, 0);
print_clear(); print_clear();
print("Keyboard state:", 0, 0);
print("multi-getkey ^^", 6, 7);
while(1) while(1)
{ {
@ -114,6 +122,8 @@ void keyboard_test(void)
#undef hexa #undef hexa
} }
timer_stop(TIMER_USER);
} }
/* /*

Binary file not shown.

BIN
icon.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -35,6 +35,12 @@ enum BlendingMode
Blend_Checker = 0x10, Blend_Checker = 0x10,
}; };
/*
enum ImageFormat
Describes the various image formats available. Colors may be encoded
as monochrome (1 layer) or gray (2 layers). Whatever the color map, any
bitmap may also have an additional alpha layer.
*/
enum ImageFormat enum ImageFormat
{ {
ImageFormat_Mono = 0x01, ImageFormat_Mono = 0x01,
@ -45,6 +51,13 @@ enum ImageFormat
ImageFormat_ColorMask = 0x0f, ImageFormat_ColorMask = 0x0f,
}; };
/*
struct Image
This structure holds information about a bitmap encoded with fxconv.
Data is accessed using longword operations, which *requires* many
sizes to be multiples of 4 (structure alignment, data alignment, layer
size, ...).
*/
struct Image struct Image
{ {
unsigned char width; unsigned char width;
@ -57,11 +70,12 @@ struct Image
const unsigned char __attribute__((aligned(4))) data[]; const unsigned char __attribute__((aligned(4))) data[];
} __attribute__((aligned(4))); } __attribute__((aligned(4)));
// Useful shorthand for user code.
typedef struct Image Image; typedef struct Image Image;
// A few other constants.
#define DISPLAY_WIDTH 128 #define DISPLAY_WIDTH 128
#define DISPLAY_HEIGHT 64 #define DISPLAY_HEIGHT 64
@ -73,18 +87,31 @@ typedef struct Image Image;
/* /*
display_getLocalVRAM() display_getLocalVRAM()
Returns the local video ram. This address should not be used directly Returns the local video ram. This function always return the same
when running the gray engine. address.
The buffer returned by this function should not be used directly when
running the gray engine.
@return Video ram address of the monochrome display module. @return Video ram address of the monochrome display module.
*/ */
void *display_getLocalVRAM(void); void *display_getLocalVRAM(void);
/*
display_getCurrentVRAM()
Returns the current video ram. This function usually returns the
parameter of the last call to display_useVRAM(), unless the gray engine
is running (in which case the result is undefined). Returns the local
vram address by default.
*/
void *display_getCurrentVRAM(void);
/* /*
display_useVRAM() display_useVRAM()
Changes the current video ram address. Expects a *4-aligned* 1024-byte Changes the current video ram address. The argument *MUST* be a
buffer. 4-aligned 1024 buffer ; otherwise any drawing operation will crash the
Do not use this function while running the gray engine. program.
This function will most likely have no effect when running the gray
engine.
@arg New video ram address. @arg New video ram address.
*/ */
@ -169,7 +196,7 @@ void dline(int x1, int y1, int x2, int y2, enum Color color);
/* /*
dimage() dimage()
Displays an image in the vram. Displays an image in the vram. Does a real lot of optimization.
@arg image @arg image
@arg x @arg x

View file

@ -22,19 +22,38 @@ unsigned int gint_getVBR(void);
*/ */
unsigned int gint_systemVBR(void); unsigned int gint_systemVBR(void);
/*
enum RTCFrequency
Describes the possible frequencies available for the real-time clock
interrupt.
*/
enum RTCFrequency
{
RTCFreq_500mHz = 7,
RTCFreq_1Hz = 6,
RTCFreq_2Hz = 5,
RTCFreq_4Hz = 4,
RTCFreq_16Hz = 3,
RTCFreq_64Hz = 2,
RTCFreq_256Hz = 1,
};
/* /*
gint_setRTCCallback() gint_setRTCCallback()
Sets the callback function for the real-time clock interrupt. If Sets the callback function for the real-time clock interrupt. If
frequency is non-NULL, the clock frequency is set to the given value. frequency is non-NULL, the clock frequency is set to the given value.
@arg callback Callback function.
@arg frequency Interrupt frequency.
*/ */
void gint_setRTCCallback(void (*callback)(void), enum GintFrequency frequency); void gint_setRTCCallback(void (*callback)(void), enum RTCFrequency frequency);
/* /*
gint_getRTCCallback() gint_getRTCCallback()
Returns the callback function. If frequency is non-NULL, it is set to Returns the callback function. If frequency is non-NULL, it is set to
the current frequency value. the current frequency value.
*/ */
void (*(gint_getRTCCallback)(void))(enum GintFrequency *frequency); void (*gint_getRTCCallback(enum RTCFrequency *frequency))(void);
@ -89,13 +108,29 @@ void gint_stop_7305(void);
gint() gint()
Handles interrupts. Handles interrupts.
*/ */
void gint(void) __attribute__(( void gint(void) __attribute__((section(".gint.int.entry"),
section(".gint.int.entry"), interrupt_handler));
interrupt_handler
));
void gint_7705(void) __attribute__((section(".gint.int"))); void gint_7705(void) __attribute__((section(".gint.int")));
void gint_7305(void) __attribute__((section(".gint.int"))); void gint_7305(void) __attribute__((section(".gint.int")));
/*
gint_setRTCFrequency()
Sets the RTC interrupt frequency and enables interrupts.
@arg frequency
*/
void gint_setRTCFrequency_7705(enum RTCFrequency frequency);
void gint_setRTCFrequency_7305(enum RTCFrequency frequency);
/*
gint_getRTCFrequency()
Returns the RTC interrupt frequency.
@return RTC interrupt frequency.
*/
enum RTCFrequency gint_getRTCFrequency_7705(void);
enum RTCFrequency gint_getRTCFrequency_7305(void);
//--- //---

View file

@ -49,4 +49,17 @@ extern enum MPU MPU_CURRENT;
*/ */
enum MPU getMPU(void); enum MPU getMPU(void);
//---
// Internal API.
// Referenced here for documentation purposes only. Do not call.
//---
/*
mpu_init()
Determines the MPU type and stores the result into MPU_CURRENT.
*/
void mpu_init(void) __attribute__((constructor));
#endif // _MPU_H #endif // _MPU_H

View file

@ -1,6 +1,10 @@
#ifndef _SCREEN_H #ifndef _SCREEN_H
#define _SCREEN_H 1 #define _SCREEN_H 1
//---
// Public API.
//---
/* /*
screen_display() screen_display()
Displays contents on the full screen. Expects a 1024-byte buffer. Displays contents on the full screen. Expects a 1024-byte buffer.

BIN
libc.a

Binary file not shown.

BIN
libgint.a

Binary file not shown.

View file

@ -41,7 +41,7 @@ static int *vram = local_vram;
//--- //---
// Local helper functions. // Local functions.
//--- //---
/* /*
@ -115,8 +115,8 @@ static void getmasks(int x1, int x2, unsigned int *masks)
//--- //---
/* /*
display_getVRAM() display_getLocalVRAM()
Returns the current video ram. Returns the local video ram.
@return Video ram address. @return Video ram address.
*/ */
@ -125,6 +125,17 @@ void *display_getLocalVRAM(void)
return (void *)local_vram; return (void *)local_vram;
} }
/*
display_getCurrentVRAM()
Returns the current vido ram.
@return Video ram address.
*/
void *display_getCurrentVRAM(void)
{
return (void *)vram;
}
/* /*
display_useVRAM() display_useVRAM()
Changes the current video ram address. Expects a *4-aligned* 1024-byte Changes the current video ram address. Expects a *4-aligned* 1024-byte
@ -370,7 +381,7 @@ void dline(int x1, int y1, int x2, int y2, enum Color color)
// the same : get a part of the image in an operator, shift it depending // the same : get a part of the image in an operator, shift it depending
// on the drawing x-coordinate, compute a mask that indicates which bits // on the drawing x-coordinate, compute a mask that indicates which bits
// of the operator contain information, and modify a vram long using the // of the operator contain information, and modify a vram long using the
// operator. // operator and the mask.
//--- //---
/* /*

View file

@ -1,6 +1,7 @@
#include <gint.h> #include <gint.h>
#include <mpu.h> #include <mpu.h>
#include <gray.h> #include <gray.h>
#include <stddef.h>
//--- //---
// Local variables. // Local variables.
@ -10,6 +11,8 @@ static unsigned int
new_vbr, new_vbr,
sys_vbr; sys_vbr;
static void (*rtc_callback)(void) = NULL;
//--- //---
@ -60,6 +63,42 @@ unsigned int gint_systemVBR(void)
return sys_vbr; return sys_vbr;
} }
/*
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.
@arg callback Callback function.
@arg frequency Interrupt frequency.
*/
void gint_setRTCCallback(void (*callback)(void), enum RTCFrequency frequency)
{
if(frequency < 1 || frequency > 7) return;
rtc_callback = callback;
if(isSH3())
gint_setRTCFrequency_7705(frequency);
else
gint_setRTCFrequency_7305(frequency);
}
/*
gint_getRTCCallback()
Returns the callback function. If frequency is non-NULL, it is set to
the current frequency value.
*/
void (*gint_getRTCCallback(enum RTCFrequency *frequency))(void)
{
if(!frequency) return rtc_callback;
if(isSH3())
*frequency = gint_getRTCFrequency_7705();
else
*frequency = gint_getRTCFrequency_7305();
return rtc_callback;
}
/* /*
gint() gint()
Handles interrupts. Handles interrupts.

View file

@ -15,6 +15,35 @@
//---
// Various MPU-dependent procedures.
//---
/*
gint_setRTCFrequency()
Sets the RTC interrupt frequency and enables interrupts.
@arg frequency
*/
void gint_setRTCFrequency_7305(enum RTCFrequency frequency)
{
if(frequency < 1 || frequency > 7) return;
RTC.RCR2.BYTE = (frequency << 4) | 0x09;
}
/*
gint_getRTCFrequency()
Returns the RTC interrupt frequency.
@return RTC interrupt frequency.
*/
enum RTCFrequency gint_getRTCFrequency_7305(void)
{
return (RTC.RCR2.BYTE & 0x70) >> 4;
}
//--- //---
// Keyboard management. // Keyboard management.
//--- //---
@ -272,15 +301,16 @@ void gint_setup_7305(void)
{ {
gint_priority_lock_7305(); gint_priority_lock_7305();
// Configuring the RTC to have a 16-Hz keyboard. // Saving the RTC configuration.
rcr2 = RTC.RCR2.BYTE; rcr2 = RTC.RCR2.BYTE;
RTC.RCR2.BYTE = 0x39; // Disabling RTC interrupts by default.
RTC.RCR2.BYTE = 0x09;
} }
void gint_stop_7305(void) void gint_stop_7305(void)
{ {
gint_priority_unlock_7305(); gint_priority_unlock_7305();
// Stopping the RTC interrupt. // Restoring the RTC configuration.
RTC.RCR2.BYTE = rcr2; RTC.RCR2.BYTE = rcr2;
} }

View file

@ -15,6 +15,35 @@
//---
// Various MPU-dependent procedures.
//---
/*
gint_setRTCFrequency()
Sets the RTC interrupt frequency and enables interrupts.
@arg frequency
*/
void gint_setRTCFrequency_7705(enum RTCFrequency frequency)
{
if(frequency < 1 || frequency > 7) return;
RTC.RCR2.BYTE = (frequency << 4) | 0x09;
}
/*
gint_getRTCFrequency()
Returns the RTC interrupt frequency.
@return RTC interrupt frequency.
*/
enum RTCFrequency gint_getRTCFrequency_7705(void)
{
return (RTC.RCR2.BYTE & 0x70) >> 4;
}
//--- //---
// Keyboard management. // Keyboard management.
//--- //---
@ -22,7 +51,7 @@
/* /*
kdelay() kdelay()
Used to be a low-level sleep using the watchdog, as in the system. This 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 way seems OK at least, and it doesn't create column effects as for
SH7305. SH7305.
*/ */
static void kdelay(void) static void kdelay(void)
@ -181,6 +210,7 @@ void gint_7705(void)
//--- //---
static unsigned short iprs[8]; static unsigned short iprs[8];
static unsigned char rcr2;
static void gint_priority_lock_7705(void) static void gint_priority_lock_7705(void)
{ {
@ -230,11 +260,16 @@ void gint_setup_7705(void)
{ {
gint_priority_lock_7705(); gint_priority_lock_7705();
// Configuring the RTC to have a 16-Hz keyboard. // Saving the RTC configuration.
RTC.RCR2.BYTE = 0x39; rcr2 = RTC.RCR2.BYTE;
// Disabling RTC interrupts by default.
RTC.RCR2.BYTE = 0x09;
} }
void gint_stop_7705(void) void gint_stop_7705(void)
{ {
gint_priority_unlock_7705(); gint_priority_unlock_7705();
// Restoring the RTC configuration.
RTC.RCR2.BYTE = rcr2;
} }

View file

@ -214,7 +214,7 @@ int keylast(int *repeat_count)
/* /*
keystate() keystate()
Returns the address of the keyboard state array. The returned address Returns the address of the keyboard state array. The returned address
if the handler's buffer, therefore it contains volatile data. is the handler's buffer, therefore it contains volatile data.
@return 10-byte keyboard state buffer. @return 10-byte keyboard state buffer.
*/ */

View file

@ -63,13 +63,13 @@ enum MPU getMPU(void)
return MPU_Unknown; return MPU_Unknown;
} }
static void mpu_init(void)
__attribute__((
section(".pretext"),
constructor
));
static void mpu_init(void)
/*
mpu_init()
Determines the MPU type and stores the result into MPU_CURRENT.
*/
void mpu_init(void)
{ {
MPU_CURRENT = getMPU(); MPU_CURRENT = getMPU();
} }

View file

@ -2,9 +2,14 @@
#include <mpu.h> #include <mpu.h>
#include <stddef.h> #include <stddef.h>
//---
// Internal declarations.
// Timer structure and running information (callbacks, repeats etc.)
//---
/* /*
struct Timer struct Timer
This structure handles a running timer information. This structure holds information for a running timer.
*/ */
struct Timer struct Timer
{ {
@ -17,7 +22,8 @@ static struct Timer timers[3] = { { NULL, 0 }, { NULL, 0 }, { NULL, 0 } };
/* /*
struct mod_tmu struct mod_tmu
This structure allows access to a timer using its address. This structure holds information about the timer unit (peripheral
module) registers.
*/ */
struct mod_tmu struct mod_tmu
{ {
@ -48,6 +54,10 @@ struct mod_tmu
//---
// Internal API.
//---
/* /*
timer_get() timer_get()
@ -57,7 +67,7 @@ struct mod_tmu
@arg tmu mod_tmu structure pointer address. @arg tmu mod_tmu structure pointer address.
@arg tstr mod_tstr structure pointer address. @arg tstr mod_tstr structure pointer address.
*/ */
void timer_get(int timer, struct mod_tmu **tmu, unsigned char **tstr) static void timer_get(int timer, struct mod_tmu **tmu, unsigned char **tstr)
{ {
// Using SH7705 information for SH-3-based MPUs. // Using SH7705 information for SH-3-based MPUs.
if(MPU_CURRENT == MPU_SH7337 || MPU_CURRENT == MPU_SH7355) if(MPU_CURRENT == MPU_SH7337 || MPU_CURRENT == MPU_SH7355)
@ -76,6 +86,37 @@ void timer_get(int timer, struct mod_tmu **tmu, unsigned char **tstr)
if(tmu) *tmu += timer; if(tmu) *tmu += timer;
} }
/*
timer_interrupt()
Handles the interrupt for the given timer.
@timer Timer that generated the interrupt.
*/
void timer_interrupt(int timer)
{
// Getting the timer address.
struct mod_tmu *tmu;
timer_get(timer, &tmu, NULL);
// Resetting the interrupt flag.
(*tmu).TCR.UNF = 0;
// Calling the callback function.
if(timers[timer].callback) timers[timer].callback();
// Reducing the number of repetitions left, if not infinite.
if(!timers[timer].repetitions) return;
// And stopping it if necessary.
if(timers[timer].repetitions == 1) timer_stop(timer);
else timers[timer].repetitions--;
}
//---
// Public API.
//---
/* /*
timer_start() timer_start()
Configures and starts a timer. Configures and starts a timer.
@ -135,28 +176,3 @@ void timer_stop(int timer)
// Stopping the timer. // Stopping the timer.
*tstr &= ~byte; *tstr &= ~byte;
} }
/*
timer_interrupt()
Handles the interrupt for the given timer.
@timer Timer that generated the interrupt.
*/
void timer_interrupt(int timer)
{
// Getting the timer address.
struct mod_tmu *tmu;
timer_get(timer, &tmu, NULL);
// Resetting the interrupt flag.
(*tmu).TCR.UNF = 0;
// Calling the callback function.
if(timers[timer].callback) timers[timer].callback();
// Reducing the number of repetitions left, if not infinite.
if(!timers[timer].repetitions) return;
// And stopping it if necessary.
if(timers[timer].repetitions == 1) timer_stop(timer);
else timers[timer].repetitions--;
}