105 lines
1.9 KiB
C
105 lines
1.9 KiB
C
#include <vhex/keyboard.h>
|
|
#include <vhex/drivers/cpu.h>
|
|
|
|
/* Internal cache, used like chained list.
|
|
@note:
|
|
The KEYSC have 6 key data 16-bits registers this is why we used 6 * 16 = 96
|
|
cache slots. */
|
|
struct keycache_s keycache[96];
|
|
struct keycache_s *keylist;
|
|
|
|
//---
|
|
// Private functions
|
|
//---
|
|
|
|
/* keycache_alloc() : Try to alloc a new keycache node */
|
|
static struct keycache_s *keycache_alloc(int keycode, int keyframe)
|
|
{
|
|
void *node;
|
|
|
|
cpu_atomic_start();
|
|
|
|
node = NULL;
|
|
for (int i = 0; i < 96 ; ++i) {
|
|
if (keycache[i].keycode == KEY_UNUSED) {
|
|
keycache[i].keycode = keycode;
|
|
keycache[i].keyframe = keyframe;
|
|
keycache[i].repeated = 0;
|
|
node = &keycache[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
cpu_atomic_end();
|
|
return (node);
|
|
}
|
|
|
|
//---
|
|
// Secret entries
|
|
//---
|
|
|
|
/* keycache_init() : keycache constructor */
|
|
void keycache_init(void)
|
|
{
|
|
for (int i = 0; i < 96 ; ++i) {
|
|
keycache[i].keycode = KEY_UNUSED;
|
|
keycache[i].next = NULL;
|
|
}
|
|
keylist = NULL;
|
|
}
|
|
|
|
//---
|
|
// Public API
|
|
//---
|
|
|
|
/* keycache_update() : Add / update key code node */
|
|
void keycache_update(int row, int column, uint8_t keyframe)
|
|
{
|
|
struct keycache_s *node;
|
|
uint8_t keycode;
|
|
|
|
keycode = KEYCODE_GEN(row, column);
|
|
|
|
cpu_atomic_start();
|
|
|
|
node = keylist;
|
|
while (node != NULL) {
|
|
if (node->keycode == keycode) {
|
|
node->keyframe = keyframe;
|
|
break;
|
|
}
|
|
node = node->next;
|
|
}
|
|
|
|
if (node == NULL) {
|
|
node = keycache_alloc(keycode, keyframe);
|
|
if (node != NULL) {
|
|
node->next = keylist;
|
|
keylist = node;
|
|
}
|
|
}
|
|
|
|
cpu_atomic_end();
|
|
}
|
|
|
|
/* keycache_clean() : Remove dirty node */
|
|
void keycache_clean(int keyframe)
|
|
{
|
|
struct keycache_s **current_node;
|
|
|
|
cpu_atomic_start();
|
|
|
|
current_node = &keylist;
|
|
while (*current_node != NULL) {
|
|
if ((*current_node)->keyframe != keyframe) {
|
|
(*current_node)->keycode = KEY_UNUSED;
|
|
*current_node = (*current_node)->next;
|
|
continue;
|
|
}
|
|
(*current_node)->repeated = (*current_node)->repeated + 1;
|
|
current_node = &(*current_node)->next;
|
|
}
|
|
|
|
cpu_atomic_end();
|
|
}
|