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