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)
- 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
- exhaustive save for setjmp()
- registers that need to be saved when configuring gint
_ 7305.h
_ libc

View file

@ -17,7 +17,7 @@ void print_clear(void)
{
char *empty_line = " ";
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)
{
@ -66,30 +66,38 @@ void print_hexa(unsigned int n, int digits, int x, int y)
/*
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)
{
/*
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;
timer_start(TIMER_USER, 1700, TIMER_Po_256, keyboard_test_timer, 0);
print_clear();
print("Keyboard state:", 0, 0);
print("multi-getkey ^^", 6, 7);
while(1)
{
@ -114,6 +122,8 @@ void keyboard_test(void)
#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,
};
/*
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
{
ImageFormat_Mono = 0x01,
@ -45,6 +51,13 @@ enum ImageFormat
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
{
unsigned char width;
@ -57,11 +70,12 @@ struct Image
const unsigned char __attribute__((aligned(4))) data[];
} __attribute__((aligned(4)));
// Useful shorthand for user code.
typedef struct Image Image;
// A few other constants.
#define DISPLAY_WIDTH 128
#define DISPLAY_HEIGHT 64
@ -73,18 +87,31 @@ typedef struct Image Image;
/*
display_getLocalVRAM()
Returns the local video ram. This address should not be used directly
when running the gray engine.
Returns the local video ram. This function always return the same
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.
*/
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()
Changes the current video ram address. Expects a *4-aligned* 1024-byte
buffer.
Do not use this function while running the gray engine.
Changes the current video ram address. The argument *MUST* be a
4-aligned 1024 buffer ; otherwise any drawing operation will crash the
program.
This function will most likely have no effect when running the gray
engine.
@arg New video ram address.
*/
@ -169,7 +196,7 @@ void dline(int x1, int y1, int x2, int y2, enum Color color);
/*
dimage()
Displays an image in the vram.
Displays an image in the vram. Does a real lot of optimization.
@arg image
@arg x

View file

@ -22,19 +22,38 @@ unsigned int gint_getVBR(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()
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 GintFrequency frequency);
void gint_setRTCCallback(void (*callback)(void), enum RTCFrequency 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);
void (*gint_getRTCCallback(enum RTCFrequency *frequency))(void);
@ -89,12 +108,28 @@ void gint_stop_7305(void);
gint()
Handles interrupts.
*/
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(void) __attribute__((section(".gint.int.entry"),
interrupt_handler));
void gint_7705(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);
//---
// 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

View file

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

View file

@ -17,7 +17,7 @@ typedef unsigned int jmp_buf[16];
@arg env Empty jump buffer.
*/
int setjmp(jmp_buf env);
int setjmp(jmp_buf env);
/*
longjmp()
@ -26,6 +26,6 @@ int setjmp(jmp_buf env);
@arg env Jump buffer configure with setjmp().
@arg value setjmp() will return this integer after the jump.
*/
void longjmp(jmp_buf env, int value);
void longjmp(jmp_buf env, int value);
#endif // _SETJMP_H

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,14 +115,25 @@ static void getmasks(int x1, int x2, unsigned int *masks)
//---
/*
display_getVRAM()
Returns the current video ram.
display_getLocalVRAM()
Returns the local video ram.
@return Video ram address.
*/
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;
}
/*
@ -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
// on the drawing x-coordinate, compute a mask that indicates which bits
// 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 <mpu.h>
#include <gray.h>
#include <stddef.h>
//---
// Local variables.
@ -10,6 +11,8 @@ static unsigned int
new_vbr,
sys_vbr;
static void (*rtc_callback)(void) = NULL;
//---
@ -60,6 +63,42 @@ unsigned int gint_systemVBR(void)
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()
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.
//---
@ -272,15 +301,16 @@ void gint_setup_7305(void)
{
gint_priority_lock_7305();
// Configuring the RTC to have a 16-Hz keyboard.
// Saving the RTC configuration.
rcr2 = RTC.RCR2.BYTE;
RTC.RCR2.BYTE = 0x39;
// Disabling RTC interrupts by default.
RTC.RCR2.BYTE = 0x09;
}
void gint_stop_7305(void)
{
gint_priority_unlock_7305();
// Stopping the RTC interrupt.
// Restoring the RTC configuration.
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.
//---
@ -22,7 +51,7 @@
/*
kdelay()
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.
*/
static void kdelay(void)
@ -181,6 +210,7 @@ void gint_7705(void)
//---
static unsigned short iprs[8];
static unsigned char rcr2;
static void gint_priority_lock_7705(void)
{
@ -230,11 +260,16 @@ void gint_setup_7705(void)
{
gint_priority_lock_7705();
// Configuring the RTC to have a 16-Hz keyboard.
RTC.RCR2.BYTE = 0x39;
// Saving the RTC configuration.
rcr2 = RTC.RCR2.BYTE;
// Disabling RTC interrupts by default.
RTC.RCR2.BYTE = 0x09;
}
void gint_stop_7705(void)
{
gint_priority_unlock_7705();
// Restoring the RTC configuration.
RTC.RCR2.BYTE = rcr2;
}

View file

@ -214,7 +214,7 @@ 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.
is the handler's buffer, therefore it contains volatile data.
@return 10-byte keyboard state buffer.
*/

View file

@ -63,13 +63,13 @@ enum MPU getMPU(void)
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();
}

View file

@ -2,9 +2,14 @@
#include <mpu.h>
#include <stddef.h>
//---
// Internal declarations.
// Timer structure and running information (callbacks, repeats etc.)
//---
/*
struct Timer
This structure handles a running timer information.
This structure holds information for a running timer.
*/
struct Timer
{
@ -17,7 +22,8 @@ static struct Timer timers[3] = { { NULL, 0 }, { NULL, 0 }, { NULL, 0 } };
/*
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
{
@ -48,6 +54,10 @@ struct mod_tmu
//---
// Internal API.
//---
/*
timer_get()
@ -57,7 +67,7 @@ struct mod_tmu
@arg tmu mod_tmu 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.
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;
}
/*
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()
Configures and starts a timer.
@ -135,28 +176,3 @@ void timer_stop(int timer)
// Stopping the timer.
*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--;
}