-
Notifications
You must be signed in to change notification settings - Fork 42
/
keymatrix.c
146 lines (131 loc) · 3.58 KB
/
keymatrix.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
* A keyboard matrix input driver for SDL2
*
* The basic principle is that we take the keycode and look it up
* in the provided matrix and then generate the fake keymatrix bits.
*
* As far as our code is concerned high selects for testing and high
* bits indicate key down. The actual logic for keyboards varies and
* just needs the values inverting to suit in the emulation.
*
* We assume the selection is by row and the bits by column. This is
* simmply semantics and for a keyboard that works the other way you
* can rotate the map 90 degress.
*/
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <SDL2/SDL.h>
#include "keymatrix.h"
struct keymatrix {
unsigned int rows;
unsigned int cols;
unsigned int size;
SDL_Keycode *matrix;
bool *status;
int trace;
};
/*
* Work out what this key is in the matrix
*/
static int keymatrix_find(struct keymatrix *km, SDL_Keycode keycode)
{
SDL_Keycode *m = km->matrix;
unsigned int n = 0;
while(n < km->size) {
if (*m++ == keycode)
return n;
n++;
}
return -1;
}
/*
* Update the matrix. We don't care about state change tracking and
* the like as all that the matrix interface provides is a current
* snapshot.
*/
static bool keymatrix_event(struct keymatrix *km, SDL_Keysym *keysym, bool down)
{
int n = keymatrix_find(km, keysym->sym);
/* Not a key we emulate */
if (n == -1)
return false;
if (km->trace)
fprintf(stderr, "Keysym %02x (%s) was mapped (%d, %d).\n",
(unsigned int)keysym->sym,
down ? "Down" : "Up",
n / km->cols, n % km->cols);
km->status[n] = down;
return true;
}
/*
* Returns up to 8bits of input according to the current state of
* the key matrix. Currently ignores ghosting.
*/
uint8_t keymatrix_input(struct keymatrix *km, uint16_t scanbits)
{
unsigned int row;
unsigned int col;
uint8_t r = 0;
bool *p = km->status;
/* Work out what byte code you get back. For the moment ignore ghosting
emulation */
for (row = 0; row < km->rows; row++) {
if (scanbits & (1 << row)) {
for (col = 0; col < km->cols; col++) {
if (*p++ == true) {
if (km->trace)
fprintf(stderr, "Key (%d,%d) was down and tested\n",
row, col);
r |= (1 << col);
}
}
} else
p += km->cols;
}
return r;
}
/*
* We consume the keyboard events only.
*/
bool keymatrix_SDL2event(struct keymatrix *km, SDL_Event *ev)
{
if (ev->type == SDL_KEYDOWN)
return keymatrix_event(km, &ev->key.keysym, true);
if (ev->type == SDL_KEYUP)
return keymatrix_event(km, &ev->key.keysym, false);
return false;
}
void keymatrix_free(struct keymatrix *km)
{
free(km->status);
free(km);
}
struct keymatrix *keymatrix_create(unsigned int rows, unsigned int cols, SDL_Keycode *matrix)
{
struct keymatrix *km = malloc(sizeof(struct keymatrix));
if (km == NULL) {
fprintf(stderr, "Out of memory.\n");
exit(1);
}
memset(km, 0, sizeof(struct keymatrix));
km->rows = rows;
km->cols = cols;
km->size = rows * cols;
km->matrix = matrix;
km->status = calloc(km->size, sizeof(bool));
if (km->status == NULL) {
fprintf(stderr, "Out of memory.\n");
exit(1);
}
return km;
}
void keymatrix_reset(struct keymatrix *km)
{
}
void keymatrix_trace(struct keymatrix *km, int onoff)
{
km->trace = onoff;
}