1 // license:GPL-2.0+
2 // copyright-holders:Kevin Thacker,Sandro Ronco
3 /*********************************************************************
4
5 kc_keyb.c
6
7 KC85_2/3/4/5 Keyboard emulation
8
9 **********************************************************************
10
11 E-mail from Torsten Paul about the keyboard:
12
13 Torsten.Paul@gmx.de
14
15 "> I hope that you will be able to help me so I can add keyboard
16 > emulation to it.
17 >
18 Oh yes the keyboard caused me a lot of trouble too. I still don't
19 understand it completely.
20 A first dirty but working keyboard support is quite easy because
21 of the good and modular system rom. Most programs use the supplied
22 routines to read keyboard input so patching the right memory address
23 with the keycode that is originally supplied by the interrupt
24 routines for keyboard input will work. So if you first want to
25 have a simple start to get other things to work you can try this.
26
27 * write keycode (ascii) to address IX+0dh (0x1fd)
28 * set bit 0 at address IX+08h (0x1f8) - simply writing 01h
29 worked for me but some other bits are used too
30 this bit is reset if the key is read by the system
31
32 > From the schematics I see that the keyboard is linked to the CTC and PIO,
33 > but I don't understand it fully.
34 > Please can you tell me more about how the keyboard is scanned?
35 >
36 The full emulation is quite tricky and I still have some programs that
37 behave odd. (A good hint for a correct keyboard emulation is Digger ;-).
38
39 Ok, now the technical things:
40
41 The keyboard of the KC is driven by a remote control circuit that is
42 originally designed for infrared remote control. This one was named
43 U807 and I learned there should be a similar chip called SAB 3021
44 available but I never found the specs on the web. The SAB 3021 was
45 produced by Valvo which doesn't exist anymore (bought by Philips
46 if I remember correctly). If you have more luck finding the specs
47 I'm still interested.
48 There also was a complementary chip for the receiving side but that
49 was not used in the KC unfortunately. They choosed to measure the
50 pulses sent by the U807 via PIO and CTC.
51
52 Anyway here is what I know about the protocol:
53
54 The U807 sends impulses with equal length. The information is
55 given by the time between two impulses. Short time means bit is 1
56 long time mean bit is 0. The impulses are modulated by a 62.5 kHz
57 Signal but that's not interesting for the emulator.
58 The timing comes from a base clock of 4 MHz that is divided
59 multiple times:
60
61 4 MHz / 64 - 62.5 kHz -> used for filtered amplification
62 62.5 kHz / 64 - 976 Hz -> 1.024 ms
63 976 / 7 - 140 Hz -> 7.2 ms
64 976 / 5 - 195 Hz -> 5.1 ms
65
66 short - 5.12 ms - 1 bit
67 long - 7.168 ms - 0 bit
68
69 +-+ +-+ +-+ +-+
70 | | | | | | | |
71 +--+ +-----+ +-------+ +-----+ +--....
72
73 | | |---0---| |--1--|
74 ^
75 |
76 Startbit = shift key
77
78 The keyboard can have 64 keys with an additional key that is used by
79 the KC as shift key. This additional key is directly connected to the
80 chip and changes the startbit. All other keys are arranged in a matrix.
81
82 The chip sends full words of 7 bits (including the startbit) at least
83 twice for each keypress with a spacing of 14 * 1.024 ms. If the key
84 is still pressed the double word is repeated after 19 * 1.024 ms.
85
86 The impulses trigger the pio interrupt line for channel B that
87 triggers the time measurement by the CTC channel 3."
88
89
90 **********************************************************************
91
92
93 The CTC timer 3 count is initialised at 0x08f and counts down.
94
95 The pulses are connected into PIO /BSTB and generate a interrupt
96 on a positive edge. A pulse will not get through if BRDY from PIO is
97 not true!
98
99 Then the interrupt occurs, the CTC count is read. The time between
100 pulses is therefore measured by the CTC.
101
102 The time is checked and depending on the value the KC detects
103 a 1 or 0 bit sent from the keyboard.
104
105 Summary From code below:
106
107 0x065<=count<0x078 -> 0 bit "short pulse"
108 0x042<=count<0x065 -> 1 bit "long pulse"
109 count<0x014 -> ignore
110 count>=0x078 -> ignore
111 0x014<=count<0x042 -> signal end of code "very long pulse"
112
113 codes are sent bit 0, bit 1, bit 2...bit 7. bit 0 is the state
114 of the shift key.
115
116 Torsten's e-mail indicates "short pulse" for 1 bit, and "long
117 pulse" for 0 bit, but I found this to be incorrect. However,
118 the timings are correct.
119
120
121 Keyboard reading procedure extracted from KC85/4 system rom:
122
123 0345 f5 push af
124 0346 db8f in a,(#8f) ; get CTC timer 3 count
125 0348 f5 push af
126 0349 3ea7 ld a,#a7 ; channel 3, enable int, select counter mode, control word
127 ; write, software reset, time constant follows
128 034b d38f out (#8f),a
129 034d 3e8f ld a,#8f ; time constant
130 034f d38f out (#8f),a
131 0351 f1 pop af
132
133 0352 fb ei
134 0353 b7 or a ; count is over
135 0354 284d jr z,#03a3 ;
136
137 ;; check count is in range
138 0356 fe14 cp #14
139 0358 3849 jr c,#03a3 ;
140 035a fe78 cp #78
141 035c 3045 jr nc,#03a3 ;
142
143 ;; at this point, time must be between #14 and #77 to be valid
144
145 ;; if >=#65, then carry=0, and a 0 bit has been detected
146
147 035e fe65 cp #65
148 0360 303d jr nc,#039f ; (61)
149
150 ;; if <#65, then a 1 bit has been detected. carry is set with the addition below.
151 ;; a carry will be generated if the count is >#42
152
153 ;; therefore for a 1 bit to be generated, then #42<=time<#65
154 ;; must be true.
155
156 0362 c6be add a,#be
157 0364 3839 jr c,#039f ; (57)
158
159 ;; this code appears to take the transmitted scan-code
160 ;; and converts it into a useable code by the os???
161 0366 e5 push hl
162 0367 d5 push de
163 ;; convert hardware scan-code into os code
164 0368 dd7e0c ld a,(ix+#0c)
165 036b 1f rra
166 036c ee01 xor #01
167 036e dd6e0e ld l,(ix+#0e)
168 0371 dd660f ld h,(ix+#0f)
169 0374 1600 ld d,#00
170 0376 5f ld e,a
171 0377 19 add hl,de
172 0378 7e ld a,(hl)
173 0379 d1 pop de
174 037a e1 pop hl
175
176 ;; shift lock pressed?
177 037b ddcb087e bit 7,(ix+#08)
178 037f 200a jr nz,#038b
179 ;; no.
180
181 ;; alpha char?
182 0381 fe40 cp #40
183 0383 3806 jr c,#038b
184 0385 fe80 cp #80
185 0387 3002 jr nc,#038b
186 ;; yes, it is a alpha char
187 ;; force to lower case
188 0389 ee20 xor #20
189
190 038b ddbe0d cp (ix+#0d) ;; same as stored?
191 038e 201d jr nz,#03ad
192
193 ;; yes - must be held for a certain time before it can repeat?
194 0390 f5 push af
195 0391 3ae0b7 ld a,(#b7e0)
196 0394 ddbe0a cp (ix+#0a)
197 0397 3811 jr c,#03aa
198 0399 f1 pop af
199
200 039a dd340a inc (ix+#0a) ;; incremenent repeat count?
201 039d 1804 jr #03a3
202
203 ;; update scan-code received so far
204
205 039f ddcb0c1e rr (ix+#0c) ; shift in 0 or 1 bit depending on what has been selected
206
207 03a3 db89 in a,(#89) ; used to clear brdy
208 03a5 d389 out (#89),a
209 03a7 f1 pop af
210 03a8 ed4d reti
211
212 03aa f1 pop af
213 03ab 1808 jr #03b5
214
215 ;; clear count
216 03ad dd360a00 ld (ix+#0a),#00
217
218 ;; shift lock?
219 03b1 fe16 cp #16
220 03b3 2809 jr z,#03be
221
222 ;; store char
223 03b5 dd770d ld (ix+#0d),a
224 03b8 ddcb08c6 set 0,(ix+#08)
225 03bc 18e5 jr #03a3
226
227 ;; toggle shift lock on/off
228 03be dd7e08 ld a,(ix+#08)
229 03c1 ee80 xor #80
230 03c3 dd7708 ld (ix+#08),a
231 ;; shift/lock was last key pressed
232 03c6 3e16 ld a,#16
233 03c8 18eb jr #03b5
234
235 03ca b7 or a
236 03cb ddcb0846 bit 0,(ix+#08)
237 03cf c8 ret z
238 03d0 dd7e0d ld a,(ix+#0d)
239 03d3 37 scf
240 03d4 c9 ret
241 03d5 cdcae3 call #e3ca
242 03d8 d0 ret nc
243 03d9 ddcb0886 res 0,(ix+#08)
244 03dd c9 ret
245 03de cdcae3 call #e3ca
246 03e1 d0 ret nc
247 03e2 fe03 cp #03
248 03e4 37 scf
249 03e5 c8 ret z
250 03e6 a7 and a
251 03e7 c9 ret
252
253
254 Keyboard reading procedure extracted from KC85/3 rom:
255
256
257 019a f5 push af
258 019b db8f in a,(#8f)
259 019d f5 push af
260 019e 3ea7 ld a,#a7
261 01a0 d38f out (#8f),a
262 01a2 3e8f ld a,#8f
263 01a4 d38f out (#8f),a
264 01a6 f1 pop af
265 01a7 ddcb085e bit 3,(ix+#08)
266 01ab ddcb089e res 3,(ix+#08)
267 01af 2055 jr nz,#0206 ; (85)
268
269 01b1 fe65 cp #65
270 01b3 3054 jr nc,#0209
271
272
273 ;; count>=#65 = 0 bit
274 ;; #44<=count<#65 = 1 bit
275 ;; count<#44 = end of code
276
277 01b5 fe44 cp #44
278 01b7 3053 jr nc,#020c
279 01b9 e5 push hl
280 01ba d5 push de
281 01bb ddcb0c3e srl (ix+#0c)
282 01bf dd7e08 ld a,(ix+#08)
283 01c2 e680 and #80
284 01c4 07 rlca
285 01c5 ddae0c xor (ix+#0c)
286 01c8 2600 ld h,#00
287 01ca dd5e0e ld e,(ix+#0e)
288 01cd dd560f ld d,(ix+#0f)
289 01d0 6f ld l,a
290 01d1 19 add hl,de
291 01d2 7e ld a,(hl)
292 01d3 d1 pop de
293 01d4 e1 pop hl
294 01d5 ddbe0d cp (ix+#0d)
295 01d8 2811 jr z,#01eb ; (17)
296 01da dd770d ld (ix+#0d),a
297 01dd ddcb08a6 res 4,(ix+#08)
298 01e1 ddcb08c6 set 0,(ix+#08)
299 01e5 dd360a00 ld (ix+#0a),#00
300 01e9 181b jr #0206 ; (27)
301 01eb dd340a inc (ix+#0a)
302 01ee ddcb0866 bit 4,(ix+#08)
303 01f2 200c jr nz,#0200 ; (12)
304 01f4 ddcb0a66 bit 4,(ix+#0a)
305 01f8 280c jr z,#0206 ; (12)
306 01fa ddcb08e6 set 4,(ix+#08)
307 01fe 18e1 jr #01e1 ; (-31)
308 0200 ddcb0a4e bit 1,(ix+#0a)
309 0204 20db jr nz,#01e1 ; (-37)
310 0206 f1 pop af
311 0207 ed4d reti
312 0209 b7 or a
313 020a 1801 jr #020d ; (1)
314 020c 37 scf
315 020d ddcb0c1e rr (ix+#0c)
316 0211 18f3 jr #0206 ; (-13)
317
318 *********************************************************************/
319
320
321 #include "emu.h"
322 #include "kc_keyb.h"
323
324 #define VERBOSE 0
325 #include "logmacro.h"
326
327 //**************************************************************************
328 // GLOBAL VARIABLES
329 //**************************************************************************
330
331 DEFINE_DEVICE_TYPE(KC_KEYBOARD, kc_keyboard_device, "kc_keyboard", "KC Keyboard")
332
333 //**************************************************************************
334 // Input Ports
335 //**************************************************************************
336
337 // this is a fake keyboard layout. The keys are converted into codes
338 // which are transmitted by the keyboard to the base-unit. key code can
339 // be calculated as (line*8)+bit_index
340
INPUT_PORTS_START(kc_keyboard)341 static INPUT_PORTS_START( kc_keyboard )
342 // start of keyboard scan-codes
343 // codes 0-7
344 PORT_START("KEY0")
345 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CHAR('w')
346 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHAR('a')
347 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
348 PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
349 PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME))
350 PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('-') PORT_CHAR('=')
351 PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
352 PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CHAR('y')
353 // codes 8-15
354 PORT_START("KEY1")
355 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CHAR('e')
356 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CHAR('s')
357 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
358 PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('^') PORT_CHAR(0x00AC)
359 PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Clr") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
360 PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(':') PORT_CHAR('*')
361 PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
362 PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHAR('x')
363 // codes 16-23
364 PORT_START("KEY2")
365 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CHAR('t')
366 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CHAR('f')
367 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
368 PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHAR('p')
369 PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Del") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
370 PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('@')
371 PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
372 PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CHAR('v')
373 // codes 24-31
374 PORT_START("KEY3")
375 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CHAR('u')
376 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CHAR('h')
377 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'')
378 PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHAR('o')
379 PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Ins") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
380 PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
381 PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Brk") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
382 PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CHAR('n')
383 // codes 32-39
384 PORT_START("KEY4")
385 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHAR('i')
386 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHAR('j')
387 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
388 PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
389 PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHAR('k')
390 PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
391 PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Stop") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(PAUSE))
392 PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CHAR('m')
393 // codes 40-47
394 PORT_START("KEY5")
395 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CHAR('z')
396 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CHAR('g')
397 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
398 PORT_BIT(0x08, 0x00, IPT_UNUSED)
399 PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHAR('l')
400 PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
401 PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
402 PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CHAR('b')
403 // codes 48-56
404 PORT_START("KEY6")
405 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CHAR('r')
406 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHAR('d')
407 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
408 PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('-') PORT_CHAR('|')
409 PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR('+') PORT_CHAR(';')
410 PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
411 PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
412 PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHAR('c')
413 // codes 56-63
414 PORT_START("KEY7")
415 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CHAR('q')
416 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Shift Lock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
417 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
418 PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
419 PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
420 PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
421 PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
422 PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
423 // end of keyboard scan-codes
424 PORT_START("SHIFT")
425 // has a single shift key. Mapped here to left and right shift.
426 // shift is connected to the MOC pin of the U807
427 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
428 INPUT_PORTS_END
429
430
431 //**************************************************************************
432 // LIVE DEVICE
433 //**************************************************************************
434
435 //-------------------------------------------------
436 // kc_keyboard_device - constructor
437 //-------------------------------------------------
438 kc_keyboard_device::kc_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
439 device_t(mconfig, KC_KEYBOARD, tag, owner, clock),
440 m_write_out(*this)
441 {
442 }
443
444 //-------------------------------------------------
445 // kc_keyboard_device - destructor
446 //-------------------------------------------------
447
~kc_keyboard_device()448 kc_keyboard_device::~kc_keyboard_device()
449 {
450 }
451
452 //-------------------------------------------------
453 // device_start - device-specific startup
454 //-------------------------------------------------
455
device_start()456 void kc_keyboard_device::device_start()
457 {
458 // resolve callbacks
459 m_write_out.resolve_safe();
460
461 m_timer_transmit_pulse = timer_alloc(TIMER_TRANSMIT_PULSE);
462
463 m_timer_transmit_pulse->adjust(attotime::from_usec(1024), 0, attotime::from_usec(1024));
464 }
465
466 //-------------------------------------------------
467 // device_reset - device-specific reset
468 //-------------------------------------------------
469
device_reset()470 void kc_keyboard_device::device_reset()
471 {
472 // set initial state
473 m_write_out(CLEAR_LINE);
474
475 m_transmit_buffer.pulse_sent = 0;
476 m_transmit_buffer.pulse_count = 0;
477
478 memset(&m_transmit_buffer, 0, sizeof(m_transmit_buffer));
479 }
480
481 //-------------------------------------------------
482 // input_ports - device-specific input ports
483 //-------------------------------------------------
484
device_input_ports() const485 ioport_constructor kc_keyboard_device::device_input_ports() const
486 {
487 return INPUT_PORTS_NAME( kc_keyboard );
488 }
489
490 //-------------------------------------------------
491 // device_timer - handler timer events
492 //-------------------------------------------------
493
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)494 void kc_keyboard_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
495 {
496 switch(id)
497 {
498 case TIMER_TRANSMIT_PULSE:
499 if (m_transmit_buffer.pulse_sent < m_transmit_buffer.pulse_count)
500 {
501 // byte containing pulse state
502 int pulse_byte_count = m_transmit_buffer.pulse_sent>>3;
503 // bit within byte containing pulse state
504 int pulse_bit_count = 7 - (m_transmit_buffer.pulse_sent & 0x07);
505
506 // get current pulse state
507 int pulse_state = (m_transmit_buffer.data[pulse_byte_count]>>pulse_bit_count) & 0x01;
508
509 LOG("KC keyboard sending pulse: %02x\n", pulse_state);
510
511 // send pulse
512 m_write_out(pulse_state ? ASSERT_LINE : CLEAR_LINE);
513
514 // update counts
515 m_transmit_buffer.pulse_sent++;
516 }
517 else
518 {
519 // if there is nothing to send, rescan the keyboard
520 static const char *const keynames[] = { "KEY0", "KEY1", "KEY2", "KEY3", "KEY4", "KEY5", "KEY6", "KEY7" };
521
522 m_transmit_buffer.pulse_sent = 0;
523 m_transmit_buffer.pulse_count = 0;
524
525 // scan all lines (excluding shift)
526 for (int i=0; i<8; i++)
527 {
528 uint8_t keyboard_line_data = ioport(keynames[i])->read();
529
530 // scan through each bit
531 for (int b=0; b<8; b++)
532 {
533 // is pressed?
534 if ((keyboard_line_data & (1<<b)) != 0)
535 {
536 // generate fake code
537 uint8_t code = (i<<3) | b;
538 LOG("Code: %02x\n",code);
539
540 transmit_scancode(code);
541 }
542 }
543 }
544 }
545 break;
546 }
547 }
548
549
550 //-------------------------------------------------
551 // add a pulse
552 //-------------------------------------------------
553
add_pulse_to_transmit_buffer(int pulse_state,int pulse_number)554 void kc_keyboard_device::add_pulse_to_transmit_buffer(int pulse_state, int pulse_number)
555 {
556 if (m_transmit_buffer.pulse_count + 1 < TRANSMIT_BUFFER_LENGTH)
557 {
558 for (int i=0; i<pulse_number; i++)
559 {
560 int pulse_byte_count = m_transmit_buffer.pulse_count>>3;
561 int pulse_bit_count = 7-(m_transmit_buffer.pulse_count & 0x07);
562
563 if (pulse_state)
564 m_transmit_buffer.data[pulse_byte_count] |= (1<<pulse_bit_count);
565 else
566 m_transmit_buffer.data[pulse_byte_count] &= ~(1<<pulse_bit_count);
567
568 m_transmit_buffer.pulse_count++;
569 }
570 }
571 }
572
573 //-------------------------------------------------
574 // fill transmit buffer with pulse for 0 or 1 bit
575 //-------------------------------------------------
576
add_bit(int bit)577 void kc_keyboard_device::add_bit(int bit)
578 {
579 if (bit)
580 add_pulse_to_transmit_buffer(0, 7);
581 else
582 add_pulse_to_transmit_buffer(0, 5);
583
584 // "end of bit" pulse -> end of time for bit
585 add_pulse_to_transmit_buffer(1);
586 }
587
588
589 //-------------------------------------------------
590 // begin pulse transmit
591 //-------------------------------------------------
592
transmit_scancode(uint8_t scan_code)593 void kc_keyboard_device::transmit_scancode(uint8_t scan_code)
594 {
595 // initial pulse -> start of code
596 add_pulse_to_transmit_buffer(1);
597
598 // state of shift key
599 add_bit((ioport("SHIFT")->read() & 0x01)^0x01);
600
601 for (int i=0; i<6; i++)
602 {
603 // each bit in turn
604 add_bit(scan_code & (1<<i));
605 }
606
607 // signal end of scan-code
608 add_pulse_to_transmit_buffer(0, 14);
609
610 add_pulse_to_transmit_buffer(1);
611
612 // back to original state
613 add_pulse_to_transmit_buffer(0);
614 }
615