diff --git a/TODO b/TODO index 3f7b8de..5be8293 100644 --- a/TODO +++ b/TODO @@ -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 diff --git a/demo/gintdemo.c b/demo/gintdemo.c index b9b92f6..a65dad6 100644 --- a/demo/gintdemo.c +++ b/demo/gintdemo.c @@ -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; diff --git a/demo/gintdemo.h b/demo/gintdemo.h index 1d32bcd..2b4fc24 100644 --- a/demo/gintdemo.h +++ b/demo/gintdemo.h @@ -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() diff --git a/demo/test_keyboard.c b/demo/test_keyboard.c index ab90268..0ab410d 100644 --- a/demo/test_keyboard.c +++ b/demo/test_keyboard.c @@ -2,13 +2,9 @@ #include #include #include +#include -/* - 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); } } diff --git a/demo/test_timer.c b/demo/test_timer.c index d8158b5..53e8bd0 100644 --- a/demo/test_timer.c +++ b/demo/test_timer.c @@ -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; diff --git a/include/events.h b/include/events.h index 01e5277..b1832a4 100644 --- a/include/events.h +++ b/include/events.h @@ -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 diff --git a/include/internals/events.h b/include/internals/events.h index 976e352..ac8b7ee 100644 --- a/include/internals/events.h +++ b/include/internals/events.h @@ -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; diff --git a/include/internals/keyboard.h b/include/internals/keyboard.h index 2824893..10bd564 100644 --- a/include/internals/keyboard.h +++ b/include/internals/keyboard.h @@ -5,7 +5,7 @@ #include // 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 diff --git a/include/internals/timer.h b/include/internals/timer.h index f15abc1..19b4a4e 100644 --- a/include/internals/timer.h +++ b/include/internals/timer.h @@ -7,7 +7,8 @@ */ struct Timer { - void (*callback)(void); + void *callback; + void *data; int repeats; }; diff --git a/include/keyboard.h b/include/keyboard.h index 4bb2483..ea27483 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -13,6 +13,7 @@ #ifndef _KEYBOARD_H #define _KEYBOARD_H 1 +#include #include //--- @@ -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 diff --git a/include/timer.h b/include/timer.h index 1b5cb7d..e231cf8 100644 --- a/include/timer.h +++ b/include/timer.h @@ -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() diff --git a/src/clock/clock.c b/src/clock/clock.c index a88a216..06426eb 100644 --- a/src/clock/clock.c +++ b/src/clock/clock.c @@ -4,6 +4,7 @@ #include #include #include +#include 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); diff --git a/src/events/event_get.c b/src/events/event_get.c index eceb1ff..5b2e707 100644 --- a/src/events/event_get.c +++ b/src/events/event_get.c @@ -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; diff --git a/src/events/event_push.c b/src/events/event_push.c index 3c47d09..0e39b2c 100644 --- a/src/events/event_push.c +++ b/src/events/event_push.c @@ -1,7 +1,7 @@ #include #include -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; diff --git a/src/gray/gray_engine.c b/src/gray/gray_engine.c index 9c1071f..fab319e 100644 --- a/src/gray/gray_engine.c +++ b/src/gray/gray_engine.c @@ -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; } diff --git a/src/keyboard/getPressedKey.c b/src/keyboard/getPressedKey.c index ca8ba32..f7d7d06 100644 --- a/src/keyboard/getPressedKey.c +++ b/src/keyboard/getPressedKey.c @@ -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; diff --git a/src/keyboard/getPressedKeys.c b/src/keyboard/getPressedKeys.c index b6dd739..c3b21f1 100644 --- a/src/keyboard/getPressedKeys.c +++ b/src/keyboard/getPressedKeys.c @@ -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; diff --git a/src/keyboard/getkey.c b/src/keyboard/getkey.c index 89e2bc5..1cbfcad 100644 --- a/src/keyboard/getkey.c +++ b/src/keyboard/getkey.c @@ -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; -} -*/ diff --git a/src/keyboard/keyboard_interrupt.c b/src/keyboard/keyboard_interrupt.c index e98dc51..9cf854a 100644 --- a/src/keyboard/keyboard_interrupt.c +++ b/src/keyboard/keyboard_interrupt.c @@ -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); } diff --git a/src/keyboard/keyboard_misc.c b/src/keyboard/keyboard_misc.c index abdf59c..6248a3d 100644 --- a/src/keyboard/keyboard_misc.c +++ b/src/keyboard/keyboard_misc.c @@ -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; } diff --git a/src/keyboard/keyboard_sh7305.c b/src/keyboard/keyboard_sh7305.c index ab515ed..8eb0bca 100644 --- a/src/keyboard/keyboard_sh7305.c +++ b/src/keyboard/keyboard_sh7305.c @@ -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); } diff --git a/src/keyboard/keyboard_sh7705.c b/src/keyboard/keyboard_sh7705.c index 1ab1800..20cd32c 100644 --- a/src/keyboard/keyboard_sh7705.c +++ b/src/keyboard/keyboard_sh7705.c @@ -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); } diff --git a/src/keyboard/multigetkey.c b/src/keyboard/multigetkey.c index dbe8a44..b1bc5e5 100644 --- a/src/keyboard/multigetkey.c +++ b/src/keyboard/multigetkey.c @@ -1,5 +1,6 @@ #include #include +#include /* 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; } diff --git a/src/timer/timer_interrupt.c b/src/timer/timer_interrupt.c index 85f4427..5b183f4 100644 --- a/src/timer/timer_interrupt.c +++ b/src/timer/timer_interrupt.c @@ -3,7 +3,11 @@ #include -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; diff --git a/src/timer/timer_start.c b/src/timer/timer_start.c index 7e7c9d6..0792702 100644 --- a/src/timer/timer_start.c +++ b/src/timer/timer_start.c @@ -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); }