Key repeat events & Timer callbacks with arguments. Fixed sleep_us().

This commit is contained in:
lephe 2017-02-25 23:19:35 +01:00
parent 0ef89df6e7
commit 7ab6170ca3
25 changed files with 264 additions and 189 deletions

19
TODO
View File

@ -9,22 +9,21 @@ Simple improvements:
- demo: Try 284x124 at (-60, -28) (all disadvantages)
- display: Rectangle-based drawing functions
- time: Compute CLOCKS_PER_SEC
- events: Introduce KeyRepeat events
- string: Use cmp/str to implement memchr() (assembler examples)
- string: Do some tests for memcmp()
- core: Register more interrupts (and understand their parameters)
- rtc: Take care of carry when reading time
- core: Register more interrupts (and understand their parameters)
- rtc: Take care of carry when reading time
Larger improvements:
- errno: Introduce errno and use it more or less everywhere
- errno: Introduce errno and use it more or less everywhere
- bopti: Monochrome bitmaps blending modes
- bopti: Handle partial transparency
- core: Implement all callbacks and a complete user API
* core: Better save registers
* core: Allow return to menu
- serial: Implement a driver
- usb: Implement a driver
- esper: Cleaner playback, synthetizing
- clock: Handle overclocking (relaunch clocks when overclocking)
* core: Better save registers
* core: Allow return to menu
- serial: Implement a driver
- usb: Implement a driver
- esper: Cleaner playback, synthetizing
- clock: Handle overclocking (relaunch clocks when overclocking)
Things to investigate:
- Packed bit fields alignment

View File

@ -300,7 +300,7 @@ void main_menu(int *category, int *app)
};
const char *list_tests[] = {
"Keyboard",
"Keyboard and events",
"Gray engine",
"Image rendering",
"Text rendering",
@ -495,6 +495,8 @@ int main(void)
{
int category, app;
sleep_ms(2000);
while(1)
{
main_menu(&category, &app);
@ -502,7 +504,7 @@ int main(void)
switch((category << 8) | app)
{
case 0x0101: test_keyboard(); break;
case 0x0101: test_keyboard_events(); break;
case 0x0102: test_gray(); break;
case 0x0103: test_bopti(); break;
case 0x0104: test_tales(); break;

View File

@ -46,10 +46,10 @@ void print(int x, int y, const char *format, ...);
//---
/*
test_keyboard()
Displays a real-time multigetkey() and the keyboard state.
test_keyboard_events()
Real-time keyboard management with events.
*/
void test_keyboard(void);
void test_keyboard_events(void);
/*
test_gray()

View File

@ -2,13 +2,9 @@
#include <display.h>
#include <keyboard.h>
#include <stdlib.h>
#include <events.h>
/*
test_keyboard()
Displays a real-time multigetkey() and the keyboard state.
*/
static void draw(volatile unsigned char *state)
static void draw_keyboard(volatile uint8_t *state)
{
int i, j, k, l;
int x, y;
@ -22,12 +18,16 @@ static void draw(volatile unsigned char *state)
if(i == 4 && j == 5) continue;
x = 5 * j + 1;
y = 61 - 5 * i;
y = 59 - 5 * i;
// Space for the horizontal line.
y += 3 * (i < 7);
// Moving the [AC/ON] key.
if(!i) x = 5 * (5) + 1, y = 61 - 5 * (4);
if(!i) x = 5 * (5) + 1, y = 61 - 5 * (4) + 1;
// Drawing a filled shape when the key is pressed.
if(state[i] & (128 >> j))
if(state[i] & (0x80 >> j))
{
for(k = -2; k <= 2; k++) for(l = -2; l <= 2; l++)
if(abs(k) + abs(l) <= 2)
@ -40,9 +40,55 @@ static void draw(volatile unsigned char *state)
if(k || l) dpixel(x + k, y + l, Color_Black);
}
}
// Binding the arrow keys together for a more visual thing.
dpixel(28, 19, Color_Black); dpixel(29, 19, Color_Black);
dpixel(28, 24, Color_Black); dpixel(29, 24, Color_Black);
dpixel(26, 21, Color_Black); dpixel(26, 22, Color_Black);
dpixel(31, 21, Color_Black); dpixel(31, 22, Color_Black);
// An horizontal line to separate parts of the keyboard.
dline(5, 28, 32, 28, Color_Black);
}
void test_keyboard(void)
typedef struct {
event_type_t type;
int key;
int repeats;
} enhanced_event_t;
static void push_history(enhanced_event_t *history, int size, event_t event)
{
#define event_eq(x, y) ((x).type == (y).type && (x).key == (y).key)
// Determining where the history ends.
int length = 0;
while(length < size && history[length].type != ET_None) length++;
// Checking if the previous event is being repeated.
if(length > 0 && event_eq(history[length - 1], event))
{
history[length - 1].repeats++;
return;
}
// Making up some space if required.
if(length == size)
{
for(int i = 0; i < size - 1; i++) history[i] = history[i + 1];
length = size - 1;
}
// Adding a new entry to the history.
history[length].type = event.type;
history[length].key = event.key;
history[length].repeats = 1;
#undef event_eq
}
static void draw_events(enhanced_event_t *history, int size)
{
const char *key_names[] = {
"F1", "F2", "F3", "F4", "F5", "F6",
@ -55,28 +101,41 @@ void test_keyboard(void)
"1", "2", "3", "+", "-", NULL,
"0", ".", "\x08", "(-)", "EXE", NULL
};
const char *event_names[] = {
"None ", "User ", "Press", "Rept.", "Rel. "
};
volatile unsigned char *state = keystate();
int keys[4] = { 0 };
int i;
for(int i = 0; i < size && history[i].type != ET_None; i++)
{
print(8, 3 + i, "%s %s", event_names[history[i].type],
key_names[keyid(history[i].key)]);
if(history[i].repeats > 1)
print(19, 3 + i, "%d", history[i].repeats);
}
}
/*
test_keyboard_events()
Real-time keyboard management with events.
*/
void test_keyboard_events(void)
{
enhanced_event_t history[5];
int history_size = 5;
event_t event;
for(int i = 0; i < history_size; i++) history[i].type = ET_None;
while(1)
{
dclear();
locate(1, 1, "Keyboard driver");
locate(8, 3, "Pressed keys:");
draw(state);
if(keys[0] == KEY_NONE) locate(9, 4, ":None");
else for(i = 0; i < 4 && keys[i] != KEY_NONE; i++)
{
locate( 9, i + 4, ":");
locate(10, i + 4, key_names[keyid(keys[i])]);
}
locate(1, 1, "Keyboard and events");
draw_keyboard(keystate());
draw_events(history, history_size);
dupdate();
multigetkey(keys, 4, 1);
if(keys[0] == KEY_EXIT && keys[1] == KEY_NONE) break;
event = waitevent();
if(event.type == ET_KeyPress && event.key == KEY_EXIT) break;
push_history(history, history_size, event);
}
}

View File

@ -35,7 +35,7 @@ static void timing_timer(void)
static void timing_start(void)
{
timer_start(TIMER_USER, 64, Clock_Hz, timing_timer, 0);
timer_start(TIMER_USER, 64, Clock_Hz, timing_timer, NULL, 0);
rtc_cb_edit(cb_id, RTCFreq_64Hz, timing_rtc);
elapsed_timer = 0;

View File

@ -9,15 +9,11 @@
#ifndef _EVENTS_H
#define _EVENTS_H
//---
// Type definitions.
//---
/*
enum EventType
event_type_t
Something user programs will surely use most often.
*/
enum EventType
typedef enum
{
EventType_None = 0,
ET_None = EventType_None,
@ -28,27 +24,32 @@ enum EventType
EventType_KeyPressed = 2,
ET_KeyPress = EventType_KeyPressed,
EventType_KeyReleased = 3,
EventType_KeyRepeated = 3,
ET_KeyRepeat = EventType_KeyRepeated,
EventType_KeyReleased = 4,
ET_KeyRel = EventType_KeyReleased,
};
} event_type_t;
/*
struct Event
event_t
Wake up, something's going on. The union member that holds information
about the event is implicitly defined by the type attribute.
*/
struct Event
typedef struct
{
enum EventType type;
event_type_t type;
union
{
// For ET_User.
void *data;
// For ET_KeyPress and ET_KeyRel.
// For ET_KeyPress, ET_KeyRepeat and ET_KeyRel.
int key;
};
};
} event_t;
@ -64,21 +65,21 @@ struct Event
allowed.
Returns non-zero on error.
*/
int event_push(struct Event event);
int event_push(event_t event);
/*
getevent()
waitevent()
Returns the next event. If no one is available, waits for something to
happen. This function uses low-level sleep and should be preferred to
active waiting using loops.
*/
struct Event getevent(void);
event_t waitevent(void);
/*
pollevent()
Returns the next event. If no one is available, returns an event whose
type is ET_None. This function always returns immediately.
*/
struct Event pollevent(void);
event_t pollevent(void);
#endif // _EVENTS_H

View File

@ -12,7 +12,7 @@
like any other queue. Trying to add an event when the queue is full
fails, and the operation is ignored.
*/
extern volatile struct Event event_queue[];
extern volatile event_t event_queue[];
extern volatile int queue_start;
extern volatile int queue_size;

View File

@ -5,7 +5,7 @@
#include <clock.h>
// Keyboard variables.
extern volatile unsigned char keyboard_state[10];
extern volatile uint8_t keyboard_state[10];
extern volatile int interrupt_flag;
// Key statistics.
@ -19,7 +19,7 @@ extern unsigned cb_id;
getPressedKey()
Finds a pressed key in the keyboard state and returns it.
*/
int getPressedKey(volatile unsigned char *keyboard_state);
int getPressedKey(volatile uint8_t *keyboard_state);
/*
getPressedKeys()
@ -28,7 +28,13 @@ int getPressedKey(volatile unsigned char *keyboard_state);
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);
int getPressedKeys(volatile uint8_t *keyboard_state, int *keys, int count);
/*
keyboard_updateState()
Updates the keyboard state.
*/
void keyboard_updateState_7705(volatile uint8_t *state);
void keyboard_updateState_7305(volatile uint8_t *state);
#endif // _INTERNALS_KEYBOARD_H

View File

@ -7,7 +7,8 @@
*/
struct Timer
{
void (*callback)(void);
void *callback;
void *data;
int repeats;
};

View File

@ -13,6 +13,7 @@
#ifndef _KEYBOARD_H
#define _KEYBOARD_H 1
#include <stdint.h>
#include <rtc.h>
//---
@ -232,7 +233,7 @@ int keylast(int *repeat_count);
functions, but the buffer data is very volatile. Therefore, data
written to the buffer could be replaced anytime.
*/
volatile unsigned char *keystate(void);
volatile uint8_t *keystate(void);
@ -268,37 +269,4 @@ 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);
/*
keyboard_updateState()
Updates the keyboard state.
*/
void keyboard_updateState_7705(volatile unsigned char *state);
void keyboard_updateState_7305(volatile unsigned char *state);
/*
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

@ -48,17 +48,22 @@
not running the gray engine.
Unit names are defined in the clock.h header and must be one of the
following:
- Clock_us (microseconds)
- Clock_ms (milliseconds)
- Clock_s (seconds)
- Clock_Hz (hertz)
- Clock_kHz (kilohertz)
- Clock_MHz (megahertz)
- Clock_us (microseconds)
- Clock_ms (milliseconds)
- Clock_s (seconds)
- Clock_Hz (hertz)
- Clock_kHz (kilohertz)
- Clock_MHz (megahertz)
The number of repeats may to set to 0. In this case, the timer will not
stop until timer_stop() is explicitly called.
The callback is expected to be a function of the following type:
- void callback(void) if data == NULL
- void callback(void *data) if data is non-NULL
In the latter case, the data pointer will be passed as argument to the
callback function.
*/
void timer_start(int timer, int delay_or_frequency, enum ClockUnit unit,
void (*callback)(void), int repeats);
void *callback, void *data, int repeats);
/*
timer_start2()
@ -71,8 +76,8 @@ void timer_start(int timer, int delay_or_frequency, enum ClockUnit unit,
- TIMER_Po_256
- TIMER_TCLK
*/
void timer_start2(int timer, int delay, int prescaler, void (*callback)(void),
int repeats);
void timer_start2(int timer, int delay, int prescaler, void *callback,
void *data, int repeats);
/*
timer_stop()

View File

@ -4,6 +4,7 @@
#include <rtc.h>
#include <stddef.h>
#include <mpu.h>
#include <stdint.h>
static clock_config_t conf = {
.FLL = -1, .PLL = -1,
@ -21,27 +22,36 @@ static clock_config_t conf = {
int clock_setting(int duration, enum ClockUnit unit)
{
if(conf.Pphi_f <= 0) return -1;
int f = conf.Pphi_f >> 2;
uint64_t f = conf.Pphi_f >> 2;
uint64_t result;
switch(unit)
{
case Clock_us:
return (duration * f) / 1000000;
result = (duration * f) / 1000000;
break;
case Clock_ms:
return (duration * f) / 1000;
result = (duration * f) / 1000;
break;
case Clock_s:
return (duration * f);
result = (duration * f);
break;
case Clock_Hz:
return f / duration;
result = f / duration;
break;
case Clock_kHz:
return f / (duration * 1000);
result = f / (duration * 1000);
break;
case Clock_MHz:
return f / (duration * 1000000);
result = f / (duration * 1000000);
break;
default:
return -1;
}
return (result > 0xffffffff) ? (0xffffffff) : (result);
}
/*
@ -60,7 +70,7 @@ clock_config_t clock_config(void)
void sleep(void)
{
__asm__(
"sleep\n\t"
"sleep"
);
}
@ -71,10 +81,9 @@ void sleep(void)
than requested.
*/
static volatile int sleep_done = 0;
static void sleep_callback(void)
static void sleep_callback(void *flag)
{
sleep_done = 1;
*((int *)flag) = 1;
}
void sleep_ms(int ms_delay)
@ -83,8 +92,10 @@ void sleep_ms(int ms_delay)
}
void sleep_us(int us_delay)
{
sleep_done = 0;
timer_start(TIMER_USER, us_delay, Clock_us, sleep_callback, 1);
volatile int sleep_done = 0;
timer_start(TIMER_USER, us_delay, Clock_us, sleep_callback,
(void *)&sleep_done, 1);
do sleep();
while(!sleep_done);
}
@ -133,6 +144,7 @@ void clock_measure(void)
tmu->TCR.CKEG = 0;
timers[TIMER_USER].callback = NULL;
timers[TIMER_USER].data = NULL;
timers[TIMER_USER].repeats = 0;
cb_id_7705 = rtc_cb_add(RTCFreq_256Hz, clock_measure_7705, 0);

View File

@ -7,9 +7,9 @@
Returns the next event. If no one is available, returns an event whose
type is ET_None. This function always returns immediately.
*/
struct Event pollevent(void)
event_t pollevent(void)
{
struct Event event = {
event_t event = {
.type = ET_None
};
if(queue_size <= 0) return event;
@ -24,14 +24,14 @@ struct Event pollevent(void)
}
/*
getevent()
waitevent()
Returns the next event. If no one is available, waits for something to
happen. This function uses low-level sleep and should be preferred to
active waiting using loops.
*/
struct Event getevent(void)
event_t waitevent(void)
{
struct Event event;
event_t event;
while((event = pollevent()).type == ET_None) sleep();
return event;

View File

@ -1,7 +1,7 @@
#include <internals/events.h>
#include <events.h>
volatile struct Event event_queue[EVENTS_QUEUE_SIZE];
volatile event_t event_queue[EVENTS_QUEUE_SIZE];
volatile int queue_start = 0;
volatile int queue_size = 0;
@ -11,7 +11,7 @@ volatile int queue_size = 0;
or pollevent() later. Pushing ET_None events is not allowed.
Returns non-zero on error.
*/
int event_push(struct Event event)
int event_push(event_t event)
{
if(queue_size >= EVENTS_QUEUE_SIZE) return 1;
if(event.type == ET_None) return 2;

View File

@ -68,7 +68,8 @@ void gray_start(void)
{
if(runs) return;
timer_start2(TIMER_GRAY, delays[0], GRAY_PRESCALER, gray_interrupt, 0);
timer_start2(TIMER_GRAY, delays[0], GRAY_PRESCALER, gray_interrupt,
NULL, 0);
current &= 1;
runs = 1;
}

View File

@ -4,7 +4,7 @@
getPressedKey()
Finds a pressed key in the keyboard state and returns it.
*/
int getPressedKey(volatile unsigned char *keyboard_state)
int getPressedKey(volatile uint8_t *keyboard_state)
{
int row = 1, column = 0;
int state;

View File

@ -5,8 +5,7 @@
Find 'count' pressed keys in the keyboard state and fills the 'keys'
array. Returns the number of actually-pressed keys found.
*/
int getPressedKeys(volatile unsigned char *keyboard_state, int *keys,
int count)
int getPressedKeys(volatile uint8_t *keyboard_state, int *keys, int count)
{
int row = 1, column;
int found = 0, actually_pressed;

View File

@ -25,7 +25,7 @@ int getkey(void)
If max_cycles is non-zero and positive, getkey_opt() will return
KEY_NOEVENT if no event occurs during max_cycle analysis.
*/
void getkey_opt_wait(int *cycles)
static void getkey_opt_wait(int *cycles)
{
while(!interrupt_flag) sleep();
interrupt_flag = 0;
@ -34,7 +34,7 @@ void getkey_opt_wait(int *cycles)
}
int getkey_opt(enum GetkeyOpt options, int cycles)
{
struct Event event;
event_t event;
int modifier = 0;
static int event_ref = 0;
@ -120,19 +120,3 @@ int getkey_opt(enum GetkeyOpt options, int cycles)
event_ref = 0;
return KEY_NONE;
}
/*
int getkey_opt(enum GetkeyOpt options, int max_cycles)
{
while(max_cycles != 0)
{
// Handling "new key" events.
// Handling key repetitions.
}
// When no key was pressed during the given delay...
return KEY_NOEVENT;
}
*/

View File

@ -10,7 +10,7 @@
//---
// These ones get modified by interrupts.
volatile unsigned char keyboard_state[10] = { 0 };
volatile uint8_t keyboard_state[10] = { 0 };
volatile int interrupt_flag = 0;
// Key statistics.
@ -28,16 +28,25 @@ unsigned cb_id;
static void push_press(int keycode)
{
struct Event event = {
event_t event = {
.type = ET_KeyPress,
.key = keycode,
};
event_push(event);
}
static void push_repeat(int keycode)
{
event_t event = {
.type = ET_KeyRepeat,
.key = keycode,
};
event_push(event);
}
static void push_release(int keycode)
{
struct Event event = {
event_t event = {
.type = ET_KeyRel,
.key = keycode,
};
@ -51,7 +60,7 @@ static void push_release(int keycode)
*/
void keyboard_interrupt(void)
{
unsigned char state[10] = { 0 };
uint8_t state[10] = { 0 };
isSH3() ? keyboard_updateState_7705(state)
: keyboard_updateState_7305(state)
@ -61,8 +70,8 @@ void keyboard_interrupt(void)
// AC/ON.
if(keyboard_state[0] ^ state[0])
{
unsigned char pressed = ~keyboard_state[0] & state[0];
unsigned char released = keyboard_state[0] & ~state[0];
uint8_t pressed = ~keyboard_state[0] & state[0];
uint8_t released = keyboard_state[0] & ~state[0];
if(pressed & 1) push_press(KEY_AC_ON);
if(released & 1) push_release(KEY_AC_ON);
@ -71,19 +80,22 @@ void keyboard_interrupt(void)
for(int row = 1; row <= 9; row++)
{
unsigned char pressed = ~keyboard_state[row] & state[row];
unsigned char released = keyboard_state[row] & ~state[row];
uint8_t pressed = ~keyboard_state[row] & state[row];
uint8_t repeated = keyboard_state[row] & state[row];
uint8_t released = keyboard_state[row] & ~state[row];
keyboard_state[row] = state[row];
// Fasten this a bit.
if(!pressed && !released) continue;
if(!(pressed | repeated | released)) continue;
for(int column = 0; column < 8; column++)
{
if(pressed & 1) push_press ((column << 4) | row);
if(pressed & 1) push_press ((column << 4) | row);
if(repeated & 1) push_repeat ((column << 4) | row);
if(released & 1) push_release((column << 4) | row);
pressed >>= 1;
pressed >>= 1;
repeated >>= 1;
released >>= 1;
}
}
@ -95,7 +107,7 @@ void keyboard_interrupt(void)
keyboard_init()
Starts the keyboard timer.
*/
void keyboard_init(void)
__attribute__((constructor)) void keyboard_init(void)
{
cb_id = rtc_cb_add(RTCFreq_16Hz, keyboard_interrupt, 0);
}
@ -114,7 +126,7 @@ void keyboard_setFrequency(enum KeyboardFrequency frequency)
keyboard_quit()
Stops the keyboard timer.
*/
void keyboard_quit(void)
__attribute__((destructor)) void keyboard_quit(void)
{
rtc_cb_end(cb_id);
}

View File

@ -19,7 +19,7 @@ int keylast(int *repeat_count)
Returns the address of the keyboard state array. The returned address
is the handler's buffer, therefore it contains volatile data.
*/
volatile unsigned char *keystate(void)
volatile uint8_t *keystate(void)
{
return keyboard_state;
}

View File

@ -136,7 +136,7 @@ static int krow(int row)
keyboard_updateState()
Updates the keyboard state.
*/
void keyboard_updateState_7305(volatile unsigned char *keyboard_state)
void keyboard_updateState_7305(volatile uint8_t *keyboard_state)
{
for(int i = 0; i < 10; i++) keyboard_state[i] = krow(i);
}

View File

@ -129,7 +129,7 @@ static int krow(int row)
keyboard_updateState()
Updates the keyboard state.
*/
void keyboard_updateState_7705(volatile unsigned char *keyboard_state)
void keyboard_updateState_7705(volatile uint8_t *keyboard_state)
{
for(int i = 0; i < 10; i++) keyboard_state[i] = krow(i);
}

View File

@ -1,5 +1,6 @@
#include <keyboard.h>
#include <internals/keyboard.h>
#include <events.h>
/*
multigetkey()
@ -12,23 +13,28 @@
Setting count = 3 is generally safe.
The function returns after 'max_cycles' if no key is pressed.
*/
void multigetkey(int *keys, int count, int max_cycles)
static void multigetkey_wait(int *cycles)
{
int number;
while(!interrupt_flag) sleep();
interrupt_flag = 0;
if(!max_cycles) max_cycles = -1;
if(*cycles > 0) (*cycles)--;
}
void multigetkey(int *keys, int count, int cycles)
{
event_t event;
int number = 0;
while(max_cycles != 0)
if(count <= 0) return;
if(cycles <= 0) cycles = -1;
while(cycles != 0)
{
while(!interrupt_flag) sleep();
interrupt_flag = 0;
if(max_cycles > 0) max_cycles--;
number = getPressedKeys(keyboard_state, 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
// We want to update the last key data when multigetkey()
// returns a single key, because getkey() could be called a
// short time after we return, and send a new event for this
// key.
if(number == 1)
{
@ -37,10 +43,12 @@ void multigetkey(int *keys, int count, int max_cycles)
last_events = 0;
}
if(number) return;
if(number) break;
multigetkey_wait(&cycles);
}
// When no key was pressed during the given delay... (no need to fill
// the array, it has already been done by getPressedKeys()).
do event = pollevent();
while(event.type != ET_None);
return;
}

View File

@ -3,7 +3,11 @@
#include <stddef.h>
struct Timer timers[3] = { { NULL, 0 }, { NULL, 0 }, { NULL, 0 } };
struct Timer timers[3] = {
{ .callback = NULL, .data = NULL, .repeats = 0 },
{ .callback = NULL, .data = NULL, .repeats = 0 },
{ .callback = NULL, .data = NULL, .repeats = 0 },
};
/*
timer_interrupt()
@ -15,7 +19,20 @@ void timer_interrupt(int timer)
timer_get(timer, &tmu, NULL);
tmu->TCR.UNF = 0;
if(timers[timer].callback) timers[timer].callback();
if(timers[timer].callback)
{
if(timers[timer].data)
{
void (*fun)(void *data) = timers[timer].callback;
fun(timers[timer].data);
}
else
{
void (*fun)(void) = timers[timer].callback;
fun();
}
}
// Reducing the number of repetitions left, if not infinite.
if(!timers[timer].repeats) return;

View File

@ -5,8 +5,8 @@
timer_start2()
Configures and starts a time using a clock count and a prescaler.
*/
void timer_start2(int timer, int delay, int prescaler, void (*callback)(void),
int repeats)
void timer_start2(int timer, int delay, int prescaler, void *callback,
void *data, int repeats)
{
volatile struct mod_tmu *tmu;
volatile unsigned char *tstr;
@ -27,8 +27,9 @@ void timer_start2(int timer, int delay, int prescaler, void (*callback)(void),
tmu->TCR.CKEG = 0;
// Loading the structure information.
timers[timer].callback = callback;
timers[timer].repeats = repeats;
timers[timer].callback = callback;
timers[timer].data = data;
timers[timer].repeats = repeats;
// Starting the timer.
*tstr |= byte;
@ -39,9 +40,9 @@ void timer_start2(int timer, int delay, int prescaler, void (*callback)(void),
Configures and starts a timer using a delay, or a frequency, and the
associated unit.
*/
void timer_start(int timer, int delay, enum ClockUnit unit,
void (*callback)(void), int repeats)
void timer_start(int timer, int delay, enum ClockUnit unit, void *callback,
void *data, int repeats)
{
timer_start2(timer, clock_setting(delay, unit), TIMER_Po_4, callback,
repeats);
data, repeats);
}