2020-05-16 15:56:06 +02:00
|
|
|
#include <gint/display.h>
|
|
|
|
#include <gint/keyboard.h>
|
2021-03-11 18:14:52 +01:00
|
|
|
#include <gint/drivers/keydev.h>
|
2020-06-18 19:56:32 +02:00
|
|
|
#include <gint/gint.h>
|
2021-03-11 18:14:52 +01:00
|
|
|
#include <gint/clock.h>
|
2020-05-16 15:56:06 +02:00
|
|
|
|
|
|
|
#include <gintctl/util.h>
|
2021-03-11 18:14:52 +01:00
|
|
|
#include <gintctl/assets.h>
|
2020-05-16 15:56:06 +02:00
|
|
|
|
2021-03-11 18:14:52 +01:00
|
|
|
static void position(int row, int col, int *x, int *y, int *w, int *h)
|
2020-05-16 15:56:06 +02:00
|
|
|
{
|
|
|
|
#ifdef FX9860G
|
2021-03-11 18:14:52 +01:00
|
|
|
*x = 1 + (5 + (row>=5)) * col;
|
|
|
|
*y = 1 + 4 * row + (row >= 1) + (row >= 3);
|
|
|
|
*w = 4;
|
|
|
|
*h = 3 + (row == 0 || row >= 5);
|
|
|
|
if(row >= 5) *y += 1 + (row - 5);
|
|
|
|
if((row == 1 || row == 2) && col >= 4)
|
|
|
|
{
|
|
|
|
*x += 3 * (row == 2) - 2 * (col == 5);
|
|
|
|
*y += 1 + (row == 1) - 3 * (col == 5);
|
|
|
|
*w = 3;
|
|
|
|
}
|
2020-05-16 15:56:06 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef FXCG50
|
|
|
|
if(row == 0) *y=2, *x=7+29*col, *w=16, *h=16;
|
|
|
|
if(row >= 5) *y=108+23*(row-5), *x=2+35*col, *w=30, *h=17;
|
|
|
|
if(row >= 1 && row <= 4)
|
|
|
|
{
|
|
|
|
*y=28+18*(row-1), *x=2+29*col, *w=25, *h=18;
|
|
|
|
if(row == 1 && col == 4) *x=127, *y=37, *w=12, *h=12;
|
|
|
|
if(row == 1 && col == 5) *x=140, *y=24, *w=12, *h=12;
|
|
|
|
if(row == 2 && col == 4) *x=140, *y=50, *w=12, *h=12;
|
|
|
|
if(row == 2 && col == 5) *x=153, *y=37, *w=12, *h=12;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-03-11 18:14:52 +01:00
|
|
|
static void render_keyboard(keydev_t *d, int x0, int y0)
|
2020-05-16 15:56:06 +02:00
|
|
|
{
|
2021-03-12 13:39:26 +01:00
|
|
|
int x=0, y=0, w=0, h=0;
|
2021-03-11 18:14:52 +01:00
|
|
|
dimage(x0, y0, &img_kbd_released);
|
2020-05-16 15:56:06 +02:00
|
|
|
|
|
|
|
for(int row = 0; row < 9; row++)
|
|
|
|
{
|
|
|
|
int major = (9-row);
|
|
|
|
int key_count = (major >= 5) ? 6 : 5;
|
|
|
|
|
|
|
|
for(int col = 0; col < key_count; col++)
|
|
|
|
{
|
|
|
|
int code = (major << 4) | (col + 1);
|
|
|
|
if(code == 0x45) code = 0x07;
|
2021-03-11 18:14:52 +01:00
|
|
|
if(!keydev_keydown(d, code)) continue;
|
2020-05-16 15:56:06 +02:00
|
|
|
|
|
|
|
position(row, col, &x, &y, &w, &h);
|
2021-03-11 18:14:52 +01:00
|
|
|
dsubimage(x0+x, y0+y, &img_kbd_pressed, x,y,w,h, 0);
|
2020-05-16 15:56:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-11 18:14:52 +01:00
|
|
|
static void render_option(int x, int y, char const *name, bool enabled)
|
|
|
|
{
|
|
|
|
int w, h;
|
|
|
|
dsize(name, NULL, &w, &h);
|
|
|
|
|
2022-05-12 16:33:23 +02:00
|
|
|
if(enabled) drect(x-_(1,2), y-_(1,2), x+w+_(0,1), y+h+_(0,1), C_BLACK);
|
|
|
|
dtext(x, y, (enabled ? C_WHITE : C_BLACK), name);
|
2021-03-12 13:39:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void render_icon(int x, int y, int id)
|
|
|
|
{
|
|
|
|
int left = _(6,9) * id + _(1, 0);
|
|
|
|
int top = _(id != 3 && id != 4, 0);
|
|
|
|
int width = _(5, 9);
|
|
|
|
int height = _(7 - 2*top, 9);
|
|
|
|
dsubimage(x, y+top, &img_kbd_events, left,top,width,height, DIMAGE_NONE);
|
2021-03-11 18:14:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static char const *key_name(int key)
|
2020-05-16 15:56:06 +02:00
|
|
|
{
|
|
|
|
char const *key_names[] = {
|
|
|
|
"F1", "F2", "F3", "F4", "F5", "F6",
|
|
|
|
"SHIFT", "OPTN", "VARS", "MENU", "Left", "Up",
|
|
|
|
"ALPHA", "x^2", "^", "EXIT", "Down", "Right",
|
|
|
|
"X,O,T", "log", "ln", "sin", "cos", "tan",
|
|
|
|
"frac", "F<>D", "(", ")", ",", "->",
|
2021-03-11 18:14:52 +01:00
|
|
|
"7", "8", "9", "DEL", "AC.ON", "0x46",
|
2020-05-16 15:56:06 +02:00
|
|
|
"4", "5", "6", "*", "/", "0x47",
|
|
|
|
"1", "2", "3", "+", "-", "0x48",
|
|
|
|
"0", ".", "x10^", "(-)", "EXE", "0x49",
|
|
|
|
};
|
|
|
|
|
2021-03-11 18:14:52 +01:00
|
|
|
if(key == 0) return "N/A";
|
|
|
|
if(key == KEY_ACON) key = 0x45;
|
|
|
|
int row = 9 - (key >> 4);
|
|
|
|
int col = (key & 15) - 1;
|
|
|
|
return key_names[6*row + col];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void render(keydev_t *d, key_event_t *last_events, int counter)
|
|
|
|
{
|
2020-05-16 15:56:06 +02:00
|
|
|
key_event_t ev;
|
|
|
|
dclear(C_WHITE);
|
|
|
|
|
|
|
|
#ifdef FXCG50
|
|
|
|
row_title("Keyboard state visualizer");
|
|
|
|
int y0=190, dy=14, maxev=12;
|
2021-03-12 13:39:26 +01:00
|
|
|
int x1=290, x2=350;
|
2020-05-16 15:56:06 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef FX9860G
|
|
|
|
row_print(1, 1, "Keyboard state");
|
2021-03-11 18:14:52 +01:00
|
|
|
dimage(0, 56, &img_opt_gint_keyboard);
|
|
|
|
int y0=47, dy=7, maxev=6;
|
|
|
|
int x1=87, x2=117;
|
|
|
|
|
|
|
|
font_t const *old_font = dfont(&font_mini);
|
2020-05-16 15:56:06 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
for(int i=0, y=y0; i < maxev; i++, y-=dy)
|
|
|
|
{
|
|
|
|
ev = last_events[(counter+15 - i) % 16];
|
|
|
|
if(ev.type == KEYEV_NONE) continue;
|
|
|
|
|
2021-03-11 18:14:52 +01:00
|
|
|
int t = ev.type;
|
2021-03-12 13:39:26 +01:00
|
|
|
render_icon(x1, y+_(0,2), (t==KEYEV_DOWN ? 0 : (t==KEYEV_UP ? 1 : 2)));
|
|
|
|
dtext(x1 + _(7,11), y + 1, C_BLACK, key_name(ev.key));
|
2020-05-16 15:56:06 +02:00
|
|
|
|
2021-03-12 13:39:26 +01:00
|
|
|
if(ev.shift) render_icon(x2, y+_(0,1), 3);
|
|
|
|
if(ev.alpha) render_icon(x2 + _(5,9), y+_(0,1), 4);
|
|
|
|
}
|
2021-03-11 18:14:52 +01:00
|
|
|
|
2022-05-12 16:33:23 +02:00
|
|
|
render_keyboard(d, _(2,10), _(6,21));
|
2021-03-11 18:14:52 +01:00
|
|
|
int tr = d->tr.enabled;
|
|
|
|
|
2021-03-12 13:39:26 +01:00
|
|
|
#ifdef FX9860G
|
2021-03-11 18:14:52 +01:00
|
|
|
dtext(35, 10, C_BLACK, "Shift:");
|
|
|
|
render_option(35, 16, "Del", (tr & KEYDEV_TR_DELAYED_SHIFT) != 0);
|
|
|
|
render_option(47, 16, "Ins", (tr & KEYDEV_TR_INSTANT_SHIFT) != 0);
|
|
|
|
dtext(35, 24, C_BLACK, "Alpha:");
|
|
|
|
render_option(35, 30, "Del", (tr & KEYDEV_TR_DELAYED_ALPHA) != 0);
|
|
|
|
render_option(47, 30, "Ins", (tr & KEYDEV_TR_INSTANT_ALPHA) != 0);
|
|
|
|
render_option(35, 38, "-Mods", (tr & KEYDEV_TR_DELETE_MODIFIERS) != 0);
|
|
|
|
render_option(35, 46, "-Rels", (tr & KEYDEV_TR_DELETE_RELEASES) != 0);
|
|
|
|
render_option(64, 9, "Reps", (tr & KEYDEV_TR_REPEATS) != 0);
|
|
|
|
|
2021-03-12 13:39:26 +01:00
|
|
|
render_icon(54, 9, d->delayed_shift ? 7 : (d->pressed_shift ? 6 : 5));
|
|
|
|
render_icon(55, 23, d->delayed_alpha ? 7 : (d->pressed_alpha ? 6 : 5));
|
2021-03-11 18:14:52 +01:00
|
|
|
|
|
|
|
dtext(65, 17, C_BLACK, key_name(d->rep_key));
|
|
|
|
dprint(65, 29, C_BLACK, "L:%d", d->events_lost);
|
|
|
|
dfont(old_font);
|
2021-03-12 13:39:26 +01:00
|
|
|
#endif /* FX9860G */
|
|
|
|
|
|
|
|
#ifdef FXCG50
|
2022-05-12 16:33:23 +02:00
|
|
|
dtext(200, 30, C_BLACK, "Shift:");
|
|
|
|
render_icon(245, 30, d->delayed_shift ? 7 : (d->pressed_shift ? 6 : 5));
|
|
|
|
render_option(205, 42, "Del", (tr & KEYDEV_TR_DELAYED_SHIFT) != 0);
|
|
|
|
render_option(240, 42, "Ins", (tr & KEYDEV_TR_INSTANT_SHIFT) != 0);
|
|
|
|
|
|
|
|
dtext(200, 64, C_BLACK, "Alpha:");
|
|
|
|
render_icon(244, 64, d->delayed_alpha ? 7 : (d->pressed_alpha ? 6 : 5));
|
|
|
|
render_option(205, 76, "Del", (tr & KEYDEV_TR_DELAYED_ALPHA) != 0);
|
|
|
|
render_option(240, 76, "Ins", (tr & KEYDEV_TR_INSTANT_ALPHA) != 0);
|
|
|
|
|
|
|
|
render_option(200, 94, "DelMods", (tr & KEYDEV_TR_DELETE_MODIFIERS) != 0);
|
|
|
|
render_option(200, 108, "DelRels", (tr & KEYDEV_TR_DELETE_RELEASES) != 0);
|
|
|
|
|
|
|
|
render_option(200, 126, "Reps", (tr & KEYDEV_TR_REPEATS) != 0);
|
|
|
|
dprint(200, 140, C_BLACK, "%s (%d)", key_name(d->rep_key),
|
|
|
|
d->rep_count);
|
|
|
|
|
|
|
|
dprint(200, 158, C_BLACK, "Q:%d/%d", d->queue_next, d->queue_end);
|
|
|
|
dprint(200, 174, C_BLACK, "Lost:%d", d->events_lost);
|
2021-03-12 13:39:26 +01:00
|
|
|
#endif /* FXCG50 */
|
2020-05-16 15:56:06 +02:00
|
|
|
}
|
|
|
|
|
2021-03-11 18:14:52 +01:00
|
|
|
static int handle_event(keydev_t *d, key_event_t *last_events, int counter)
|
2020-05-16 15:56:06 +02:00
|
|
|
{
|
|
|
|
key_event_t ev = last_events[(counter + 15) % 16];
|
|
|
|
|
|
|
|
if(ev.type != KEYEV_DOWN) return 0;
|
|
|
|
if(ev.key == KEY_EXIT) return 1;
|
2021-03-11 18:14:52 +01:00
|
|
|
if(ev.key == KEY_MENU)
|
|
|
|
{
|
|
|
|
render(d, last_events, counter);
|
|
|
|
dupdate();
|
|
|
|
gint_osmenu();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
keydev_transform_t tr = keydev_transform(d);
|
|
|
|
|
|
|
|
if(ev.key == KEY_F1) tr.enabled ^= KEYDEV_TR_DELAYED_SHIFT;
|
|
|
|
if(ev.key == KEY_F2) tr.enabled ^= KEYDEV_TR_INSTANT_SHIFT;
|
|
|
|
if(ev.key == KEY_F3) tr.enabled ^= KEYDEV_TR_DELAYED_ALPHA;
|
|
|
|
if(ev.key == KEY_F4) tr.enabled ^= KEYDEV_TR_INSTANT_ALPHA;
|
2022-05-12 16:33:23 +02:00
|
|
|
if(ev.key == KEY_F5) tr.enabled ^= (KEYDEV_TR_DELETE_MODIFIERS |
|
|
|
|
KEYDEV_TR_DELETE_RELEASES);
|
|
|
|
if(ev.key == KEY_F6) tr.enabled ^= KEYDEV_TR_REPEATS;
|
2020-05-16 15:56:06 +02:00
|
|
|
|
2021-03-11 18:14:52 +01:00
|
|
|
keydev_set_transform(d, tr);
|
2020-05-16 15:56:06 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-03-11 18:14:52 +01:00
|
|
|
static int repeater(GUNUSED int key, GUNUSED int duration, GUNUSED int count)
|
|
|
|
{
|
|
|
|
if(count == 4) return -1;
|
|
|
|
|
|
|
|
/* Wait 250 ms until the next repeat */
|
|
|
|
return 250000;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* gintct_gint_keyboard: Real-time keyboard visualization */
|
2020-05-16 15:56:06 +02:00
|
|
|
void gintctl_gint_keyboard(void)
|
|
|
|
{
|
2021-03-11 18:14:52 +01:00
|
|
|
keydev_t *d = keydev_std();
|
|
|
|
keydev_transform_t tr = keydev_transform(d);
|
|
|
|
|
|
|
|
keydev_transform_t base = { .enabled = 0, .repeater = repeater };
|
|
|
|
keydev_set_transform(d, base);
|
|
|
|
|
2020-05-16 15:56:06 +02:00
|
|
|
/* All initialized with type=KEYEV_NONE */
|
|
|
|
key_event_t last_events[16] = { 0 };
|
|
|
|
key_event_t ev;
|
|
|
|
int counter = 0;
|
|
|
|
|
2021-03-11 18:14:52 +01:00
|
|
|
bool loop = true;
|
|
|
|
while(loop)
|
2020-05-16 15:56:06 +02:00
|
|
|
{
|
2021-03-11 18:14:52 +01:00
|
|
|
render(d, last_events, counter);
|
2020-05-16 15:56:06 +02:00
|
|
|
dupdate();
|
|
|
|
|
|
|
|
/* Redraw at each event if needed */
|
2022-10-09 18:12:43 +02:00
|
|
|
while((ev = keydev_read(d, false, NULL)).type == KEYEV_NONE)
|
|
|
|
sleep();
|
2021-03-11 18:14:52 +01:00
|
|
|
|
|
|
|
last_events[counter] = ev;
|
2020-05-16 15:56:06 +02:00
|
|
|
counter = (counter+1) % 16;
|
2021-03-11 18:14:52 +01:00
|
|
|
if(handle_event(d, last_events, counter)) break;
|
2020-05-16 15:56:06 +02:00
|
|
|
|
2022-10-09 18:12:43 +02:00
|
|
|
while((ev = keydev_read(d, false, NULL)).type != KEYEV_NONE
|
|
|
|
&& loop)
|
2020-05-16 15:56:06 +02:00
|
|
|
{
|
|
|
|
last_events[counter] = ev;
|
|
|
|
counter = (counter+1) % 16;
|
2021-03-11 18:14:52 +01:00
|
|
|
if(handle_event(d, last_events, counter)) loop = false;
|
2020-05-16 15:56:06 +02:00
|
|
|
}
|
|
|
|
}
|
2021-03-11 18:14:52 +01:00
|
|
|
|
|
|
|
keydev_set_transform(d, tr);
|
2020-05-16 15:56:06 +02:00
|
|
|
}
|