source: buchla-emu/emu/kbd.c@ e26a632

Last change on this file since e26a632 was ca77925, checked in by Thomas Lopatic <thomas@…>, 7 years ago

More accurate key up/down.

  • Property mode set to 100644
File size: 3.7 KB
Line 
1/*
2 * Copyright (C) 2017 The Contributors
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or (at
7 * your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * A copy of the GNU General Public License can be found in the file
15 * "gpl.txt" in the top directory of this repository.
16 */
17
18#include <all.h>
19
20#define ver(...) _ver(kbd_verbose, 0, __VA_ARGS__)
21#define ver2(...) _ver(kbd_verbose, 1, __VA_ARGS__)
22#define ver3(...) _ver(kbd_verbose, 2, __VA_ARGS__)
23
24int32_t kbd_verbose = 0;
25
26#define BUF_SZ 16
27
28static int32_t buf_hd = 0;
29static int32_t buf_tl = 0;
30static uint8_t buf[BUF_SZ];
31
32static uint8_t reg = 0;
33static bool irq = false;
34
35static void xmit(void)
36{
37 ver2("kbd xmit %d %d", buf_tl, buf_hd);
38
39 if (buf_tl >= buf_hd) {
40 return;
41 }
42
43 reg = buf[buf_tl % BUF_SZ];
44 irq = true;
45 ver2("kbd xmit 0x%02x", reg);
46
47 ++buf_tl;
48
49 if (buf_tl >= BUF_SZ) {
50 buf_hd -= BUF_SZ;
51 buf_tl -= BUF_SZ;
52 ver2("kbd adj %d %d", buf_tl, buf_hd);
53 }
54}
55
56static void out(uint8_t c)
57{
58 ver2("kbd out %d %d 0x%02x", buf_tl, buf_hd, c);
59
60 if (SDL_LockMutex(cpu_mutex) < 0) {
61 fail("SDL_LockMutex() failed: %s", SDL_GetError());
62 }
63
64 if (buf_hd >= buf_tl + BUF_SZ) {
65 err("keyboard port losing data");
66 }
67 else {
68 buf[buf_hd % BUF_SZ] = c;
69 ++buf_hd;
70
71 if (!irq) {
72 xmit();
73 }
74 }
75
76 if (SDL_UnlockMutex(cpu_mutex) < 0) {
77 fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
78 }
79}
80
81static void but_on(int32_t sig)
82{
83 out((uint8_t)(0x80 | sig));
84 out(0x01);
85}
86
87static void but_off(int32_t sig)
88{
89 out((uint8_t)(0x80 | sig));
90 out(0x00);
91}
92
93static void key_touch(int32_t sig, int32_t val)
94{
95 out((uint8_t)(0x80 | sig));
96 out(0x01);
97 out((uint8_t)val);
98}
99
100static void key_off(int32_t sig)
101{
102 out((uint8_t)(0x80 | sig));
103 out(0x00);
104}
105
106#if defined NOT_YET
107static void pot_128(int32_t sig, int32_t val)
108{
109 out((uint8_t)(0x80 | sig));
110 out((uint8_t)val);
111}
112
113static void pot_256(int32_t sig, int32_t val)
114{
115 out((uint8_t)(0x80 | sig));
116 out((uint8_t)((val >> 7) & 0x01));
117 out((uint8_t)(val & 0x7f));
118}
119#endif
120
121void kbd_key(SDL_KeyboardEvent *ev, bool dn)
122{
123 if ((ev->keysym.mod & KMOD_SHIFT) != 0 &&
124 ev->keysym.sym >= SDLK_a && ev->keysym.sym <= SDLK_x) {
125 int32_t i = ev->keysym.sym - SDLK_a;
126 ver2("kbd key %d %s", i, dn ? "dn" : "up");
127
128 if (dn) {
129 key_touch(1 + i, 0x7f);
130 }
131 else {
132 key_off(1 + i);
133 }
134
135 return;
136 }
137
138 int32_t sig;
139
140 if (ev->keysym.sym >= SDLK_0 && ev->keysym.sym <= '9') {
141 int32_t i = ev->keysym.sym - SDLK_0;
142 ver2("kbd dat %d %s", i, dn ? "dn" : "up");
143 sig = 60 + i;
144 }
145 else {
146 switch (ev->keysym.sym) {
147 case SDLK_x:
148 ver2("kbd x %s", dn ? "dn" : "up");
149 sig = 70;
150 break;
151
152 case SDLK_e:
153 ver2("kbd e %s", dn ? "dn" : "up");
154 sig = 71;
155 break;
156
157 case SDLK_m:
158 ver2("kbd m %s", dn ? "dn" : "up");
159 sig = 72;
160 break;
161
162 default:
163 return;
164 }
165 }
166
167 if (dn) {
168 but_on(sig);
169 }
170 else {
171 but_off(sig);
172 }
173}
174
175void kbd_init(void)
176{
177 ver("kbd init");
178}
179
180void kbd_quit(void)
181{
182 ver("kbd quit");
183}
184
185bool kbd_exec(void)
186{
187 ver3("kbd exec");
188 return irq;
189}
190
191uint32_t kbd_read(uint32_t off, int32_t sz)
192{
193 ver2("kbd rd %u:%d", off, sz * 8);
194
195 if (sz != 1 || off > 0) {
196 fail("invalid kbd rd %u:%d", off, sz * 8);
197 }
198
199 irq = false;
200 uint32_t res = reg;
201
202 xmit();
203
204 return res;
205}
206
207void kbd_write(uint32_t off, int32_t sz, uint32_t val)
208{
209 ver2("kbd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
210 fail("invalid kbd wr %u:%d", off, sz * 8);
211}
Note: See TracBrowser for help on using the repository browser.