1 IBM 4704 Keyboard Analysis - 6019284(62-key)
2 ============================================
7 IBM capacitive switch models:
8 6019273 Model 100 50-key (grid layout) http://kishy.ca/?p=894
9 6019284 Model 200 62-key Alpha(60% layout) http://kishy.ca/?p=894
10 6019303 Model 300 77-key Expanded Alpha http://deskthority.net/photos-f62/ibm-6019303-t8502.html
11 6020218 Model 400 107-key Full key http://kishy.ca/?p=894
13 Alps switch(vintage Green) models:
14 5954339 Japanese 102-key http://deskthority.net/post87127.html#p87127
15 6112883 Japanese 102-key http://geekhack.org/index.php?topic=52888.msg1194489#msg1194489
16 6112884 Japanese 102-key http://geekhack.org/index.php?topic=50437.msg1193047#msg1193047
17 6341739 Chinese 102-key http://geekhack.org/index.php?topic=52888.msg1176566#msg1176566
23 The IBM 4704: lots of pictures and info
24 http://kishy.ca/?p=894
25 http://imgur.com/a/LaABs
28 http://ed-thelen.org/comp-hist/IBM-ProdAnn/4700.pdf
32 4704 Keyboard Protocol
33 ======================
34 On powering up keyboard sends keyboard ID; A3h for 6019284(62-key), for example.
35 After that the keyboard enters FC command mode and waits for parameter data from host
36 so that it doesn't send any scancode until you send 'FF'(End of FC command mode).
40 -------------------------------
45 Japanese/Chinese 102-key A6h
50 Keyboard Plug from front
61 N No connection/No pin.
66 Data bits are LSB first and Pairty is odd. Clock has around 60us high and 30us low part.
68 ____ __ __ __ __ __ __ __ __ __ _______
69 Clock \_____/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
70 ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
71 Data ____/ X____X____X____X____X____X____X____X____X____X________
72 Start 0 1 2 3 4 5 6 7 P Stop
74 Start bit: can be long as 300-350us.
75 Inhibit: Pull Data line down to inhibit keyboard to send.
76 Timing: Host reads bit while Clock is hi.(rising edge)
77 Stop bit: Keyboard pulls down Data line to lo after 9th clock.
83 Data bits are LSB first and Pairty is odd. Clock has around 60us high and 30us low part.
85 ____ __ __ __ __ __ __ __ __ __ ________
86 Clock \______/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
87 ^ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___
88 Data ____|__/ X____X____X____X____X____X____X____X____X____X \___
89 | Start 0 1 2 3 4 5 6 7 P Stop
92 Start bit: can be long as 300-350us during start up and upto 2500us while key scanning
93 Request: Host pulls Clock line down to request to send a command.
94 Timing: After Request keyboard pull up Data and down Clock line to low for start bit.
95 After request host release Clock line once Data line becomes hi.
96 Host wirtes a bit while Clock is hi and Keyboard reads while low.
97 Stop bit: Host releases or pulls up Data line to hi after 9th clock and waits for keybaord pull down the line to lo.
103 Keyboard doesn't send Break code for all keys except for Alt by default.
106 ,-----------------------------------------------------------.
107 | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|**1|BS |
108 |-----------------------------------------------------------|
109 |Tab | Q| W| E| R| T| Y| U| I| O| P| ¢| \| PD2|
110 |-----------------------------------------------------------|
111 |Ctrl | A| S| D| F| G| H| J| K| L| ;| '| {}| PD3|
112 |-----------------------------------------------------------|
113 |Shif| <>| Z| X| C| V| B| N| M| ,| ,| /|**2|Shift |
114 |-----------------------------------------------------------|
115 |Reset|blk|Alt | Space |Alt |blk|Enter|
116 `-----------------------------------------------------------'
117 +----------+---------------------+----------+----------+
118 |` 00|PD1 04|Caps 20|LShift 30|Reset 31|
119 |1 18|q 05|a 21|<> 3E|Rblank 41|
120 |2 19|w 06|s 22|z 32|Alt 3F|
121 |3 1A|e 13|d 23|x 33|Space 40|
122 |4 10|r 14|f 24|c 34|Alt 3F|
123 |5 11|t 15|g 25|v 35|Lblank 42|
124 |6 12|y 16|h 26|b 36|Enter 2F|
125 |7 08|u 17|j 27|n 37| |
126 |8 09|i 01|k 28|m 38| |
127 |9 0A|o 02|l 29|, 39| |
128 |0 0F|p 03|; 2A|. 3A| |
129 |- 1F|¢ 1B|' 2B|/ 3B| |
130 |= 0D|\ 1C|{} 2C|**2 3C| |
131 |**1 0C|PD2 1D|PD3 2D|RShift 3D| |
133 +----------+---------------------+----------+----------+
134 Bit7 is 'press flag' which set 1 on press and 0 on release when break code is enabled.
136 NOTE: When break code is enabled the key sends scancode with setting 7th bit on press
137 and without it on release. That is, '`' sends 80h on press and 00h on release.
142 Keyboard accepts these commands from host.
144 Description Entry point
145 -----------------------------------------------------------
148 FD Buzzer(emits a short beep) 00edh
149 FC Set Key Flag 00f6h
156 Keyobard sends these bytes to host.
158 Description Entry point
159 -----------------------------------------------------------
160 FE Overflow(key event/receive data) 00c5h, 0346h
161 Memory test error 0224h
162 FD Command out of bound 00d8h
164 7E Read/Parity error in receive from host 00bch
165 80-FB? scan code(make)
166 00-7B? scan code(break)
167 note: Alps model spits scan code 7B(FB) at least.
170 Set Key Flag command(FC)
171 ------------------------
172 After 'Power on Reset' firmware enters this command mode and waits for data from host,
173 so that you don't need to send 'FC' and it doesn't send any scancode until you send 'FF' to exit this mode.
174 With Alps models you need to send 'FC' command to enter this mode.
180 | `-----`--- scan code
181 `------------- enable bit(0: enable repeat, 1: enable break)
185 FE Resend(011ah) no need to use
186 FF End(0114h) exits FC command mode.
188 Response from keyboard:
189 FD Out of bound - Invalid scancode
190 -- OK - No response means that command is accepted.
193 To enable break code of all keys you have to send following commands.
203 This keyboard is very power greedy, it consumes around 170mA
204 and USB port may not be able to supply enough current.
206 5.061V - No load. Power from Powered USB Hub.
207 4.946V 133.6mA max without Buzzer
208 4.911V 171.0mA max with Buzzer
213 NOTE: TWO BOLTS OF CONTROLLER BOARD IS CRITICAL.
214 Controller PCB and tab of bottom plate of key assembly with two hex bolts, these
215 connect between controller ground to the metal bottom plate of key switch assembly.
216 This connection is very critical to sense key state, keys will not be registered
217 unless they are tightened up with the bolts
219 Controller: 8048 DIP40 with 1KB ROM and 64B RAM(8748H?)
220 Clock: ??MHz Resonator? TODO: machine cycle: ??us
221 Buffer: 7917 hex buffer
222 Sensor: IBM custom chip for capacitive sense
225 8048 Pin configuration
226 ----------------------
228 bit: D7 D6 D5 D4 D3 D2 D1 D0
229 use: BZ CLK DAT ??? G S2 S1 S0
232 ----------------------------------------------------------------------
237 ??? Sensor state out(drive/charge? via 7917 buffer)
238 DAT out Data via buffer logic with 2K pull up resistor
239 CLK out Clock via buffer logic with 2K pull up resistor
240 BZ out Drive Buzzer via 7917 buffer with 2KOhm pull up resistor(H:on/L:off)
242 input of Sensor state(H:on/L:off)
244 input of Clock line with 1KOhm pull up resistor
246 input of Data line with 1KOhm pull down resistor
248 P10-P17 matrix row0-7
250 P20 matrix row8 or I(keyboard identity bits row)
256 -----------------------------
257 D0-2 ====/===== S0-2(Sensor)
258 D3 ---------- STR(Sensor)
260 D4 --|>--+--- OUT(Sensor)
264 -----------------------------
287 TCNTI disable at 0014h
290 IBM Capacitive sensor chip
291 --------------------------
292 Silver canned package
294 Pin Connection Desciption
295 ----------------------------------------------------------------
296 Input(C0-7) Matrix Col0-7 8 column line inputs
297 Col select(S0-2)8048:D0-D2 Select column line to sense
298 Strobe(STR) 8048:D3 Strobe
299 Output(OUT) 848:T0 Read Key state(0:pressed/1:released)
302 +-----------++------+-------+-------+-------+
303 | 1 2 3 4 5 ||1:LCL |6:LCC |B:S0 |G:C5 |
304 | 6 7 8 9 ||2:GND |7:LCM |C:? |H:C4 |
305 | A B ||3:Out |8:S2 |D:C6 |I:C3 |
306 | C D E F ||4:STR |9:S1 |E:C0 |J:C2 |
307 | G H I J K ||5:VCC |A:C7 |F:? |K:C1 |
308 +-----------++------+-------+-------+-------+
317 Speculation: 8048:D4 is used to prepare to sense capacitance.(charge key capcitor?)
321 D0-2=<column> ; select column S0-2
322 D4=1 ; Prepare sensor(Charge?)
323 P1/P2=<row> ; select row
324 D0-4=<default> ; 00010(bus=c2h)
326 P1/P2=0 ; unselect row
327 read T0 ; see key state
332 D0-2=2(010) ; select col2
335 P2=00h ; unselect row
343 -|--------------------------------------------------------------
344 0|Enter RShift JIS_ PD3 PD2 \| LofBS BS
345 1|RAlt RBlank /? '" {} Cent! - =
351 7|Reset LBlank ISO\ LShift CapLock PD1 `~ 1
352 8|_ x _ _ x x _ _ (Identity bits: 32h)
354 Two 15-line flat cables shown from bttom of PCB:
356 Flatcable A Flatcable B
358 0123456789ABCDE0123456789ABCDE
359 --8-----01234567----76543210--
363 Keyboard Identity Bits
364 ----------------------
365 4704 keyboards has its identity bit marks on PCB matrix and it is readable
366 from firmware so that it can select key layout depending on this.
370 http://kishy.dyndns.org/wp-content/uploads/2013/02/6019273_0011.jpg
372 http://kishy.dyndns.org/wp-content/uploads/2013/02/6019284_0020_capacitive-pcb-top.jpg
374 http://kbtalking.cool3c.com/article/23272
376 http://kishy.dyndns.org/wp-content/uploads/2011/09/6020218_distrib_0019.jpg
385 Power on Reset(0000h):
387 turns Buzzer(BZ=L) on at 0002h
388 turns Buzzer(BZ=H) off at 01adh
389 Initialize all memory(3fh-00h)
390 Initialize other registers
391 Read keyboard id and set default parameter at 01afh
392 set break flag for Alt key by default
393 Test and clear memory(3fh..00h) at 0202h
394 Test program memory at 0214h
395 r4=($21&07h)|50h at 0020h
396 Send test result at 022dh
397 sends [a0h | (keyboard id&f0h)>>4] on success
398 6019284 seneds a3h on success
399 Wait for data from host - it expects FC command data followed by ffh(end)
403 Initialize all memory(20h-00h) It retains parameter memory.
404 Initialize other registers
405 r4=($21&07h)|50h at 0020h
412 $01-07 *Bank0* Registers r0-r7
416 r3 row mask of scan 024dh, 0257h
420 | | | | | `-`-`------ Sensor column select
421 | | | | `------------ Sensor strobe?
422 | | | `-------------- Sensor column set?
423 | | `---------------- Data
424 | `------------------ Clock
425 `-------------------- Buzzer control(L:on/H:off)023ch
426 =$21&07h|50h: call 0020h at 001ch soft reset (52h=0101 0010)
427 =$21&07h|50h: call 0020h at 0109h command FC (52h=0101 0010)
428 =r4|80h: at 00f4h(FD command)
429 =r4&7fh: at 023ch(Main)
431 r5 repeat dealy/interval
436 *r6 0bh at 00edh(FD command)
438 r7 received data from host
439 temporary use at 01afh
440 temporary use at 005dh
441 =r4&c0h(current bus value?) 0247h
442 $08-17 8-level stack(2*8)
444 : last key state(1:pressed/0:released)
445 $15 (0E-15)=8*8=64 matrix(for 50-key and 62-key?)
447 : last key state(1:pressed/0:released)
448 $1C (16-1C)=7*8=56 (extension for 77-key?)
450 $18-1F *Bank1* Registers 0-r7
451 Outgoing buffer of data sent to host
452 $1D r5 outgoing buffer top
453 $1E r6 outgoing buffer
454 $1F r7 outgoing buffer bottom
457 $20 Resend buffer: code last sent used by 'Resend'(FE)
459 $21 Keyboard identity bits
460 0011 0010 (6019284: 32h read from Row(I))
462 ||| |```- Sensor chip control(bus value)??
464 ```------ keyboard model id
466 set at 01fah on Power on Reset: 32h from row8(I)(6019284)
467 got at 0020h on Soft Reset:
468 got at 034eh on translate into scan code:
469 got at 0125h on command FC:
470 set from scan 8(I) row at 01fdh
473 Model 100 6019273 50-key (grid layout): 22h(from picture)
474 Model 200 6019284 62-key Alpha(60% layout): 32h
475 Model 300 6019303 77-key Expanded Alpha: 42h?(from dump list)
476 Model 400 6020218 107-key Full key: no identity
477 Looks like this firmware does not support 107-key.
480 It seems Model 100, 200 and 300 keyboards share one firmware code and
481 have small square copper patterns on righ side of PCB to identify
482 its layout. See following pictures. Model 400 may use another firmware.
484 $22-3F 30-byte Parameter RAM(Repeat and Break flags)
485 Parameter byte is comprised of four flag pairs. Flags occupies two bits each a key.
486 Parameter RAM can have flags for 120(4*30) keys.
488 Parameter byte and flags:
490 3r 3b 2r 2b 1r 1b 0r 0b
492 $3F End of Memory(64 bytes)
499 0020 Soft Reset r4=($21&07h)|50h = (32h&07h)|50h=52h
500 0029 r1=r1+(a), a=r0 (page 0)
501 002c (F0=0: send or receive data with 'interpret command mode')
502 002d Receive data or Send scan code
505 0082 Receive data from host
506 condition: F0==0 interpret command
507 F0==1 return receive data(a)
508 return: F1=1(ERROR) 00c7 (Receive ACK/Parity Error) 00b6,00ce
510 a=recieve data, (with F0=0 00dc) F0==0 means 'data received'
511 00bc push 7f(error) into outgoing buffer
512 00be push data/response into outgoing buffer(r5,r6,r7)
513 00d2 interpret keyboard command
514 00de calculate parity
516 01a4 r1=r1+(a), a=r0 (page 1)
518 01a9 Buzzer and Scan row8(*) and set param: call from Power on Reset 0018h
519 01af Read keyboard identity bits from row8(I) and set param: - call from command FC 0107h
520 0202 Memory Test(Power on Reset)
522 0230 Main loop: send, receive data and scan
523 send/receive: call 002c
524 0263 **Scan matrix**(F1==0): F1=1, r1=15h, r2=3fh, r3=01h
525 0287 **Scan matrix**(F1==1): F1=0, r1=1ch, r2=77h, r3=02h
526 0325 get key configure flags(a=-----rb; where r:repeat enable, b:break enable)
527 0339 queue data at bottom of outgoing buffer
528 034e translate into scan code
529 scan code table1/table2
532 Keyboard command entry points
533 -----------------------------
534 FF: jump_table0 Soft Reset(008h)
535 FE: jump_table1 Resend(return content of $20)
536 FD: jump_table2 Short beep BZ
537 FC: jump_table3 parameter configuration(100h)
538 FB: jump_table4 Soft Reset(008h)
539 FA: jump_table5 Reset(000h)
544 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
546 ; 8048 Disassembly of IBM 6019284 ROM dump
548 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
549 ; label mnemonic ; address comment
550 ;-------------------------------------------------------------------------------------
552 ; jump_table:5 Hard Reset/Power on Reset
553 mov a,#07fh ; 0000 - a=7f Power on Reset
554 outl bus,a ; 0002 - BZ=L(off), others=H
555 mov r0,#03fh ; 0003 - r0=3fh
558 ; jump_table:0,4 Soft Reset
559 mov r0,#020h ; 0008 - r0=20h $20=resend buffer
565 ; hard reset clear 3f-00h F1=0
566 ; soft reset clear 20-00h F1=1
567 X000c: clr f0 ; 000c - F0=0
569 X000e: mov @r0,a ; 000e - @r0=0 r0=$3f(hard)/$20(soft)
570 djnz r0,X000e ; 000f - clear RAM 3f/20h to $00
571 mov psw,a ; 0011 - psw=0
572 outl p1,a ; 0012 - p1=0
573 outl p2,a ; 0013 - p2=0
574 dis tcnti ; 0014 - disable timer overflow
575 dis i ; 0015 - disable INT
576 jf1 X001c ; 0016 - jump if F1==1(Soft Reset?)
578 ; F1==0 Power on Reset
579 call X01a9 ; 0018 - read keyboard id and set default parameter
580 jmp X0202 ; 001a - Memory Test and go to Main
583 X001c: call X0020 ; 001c - ; r4=$21&07h|50h(52h?), a=r4
584 jmp X0230 ; 001e - ; go to Main
589 : RETURN: a=r4(original)
592 X0020: mov r0,#021h ; 0020 - r0=21h(keyboad identity bits)
593 mov a,@r0 ; 0022 - a=($21)
594 anl a,#007h ; 0023 - a=a&07h
595 orl a,#050h ; 0025 - a=a|50h
596 xch a,r4 ; 0027 - swap a,r4
599 ; read program memory @page0
601 ; OUTPUT: a=(a)@page0
602 X0029: movp a,@a ; 0029 -
603 jmp X01a5 ; 002a - r1=r1+a, a=r0
607 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
609 ; Receive data or Send scan code
610 ; INPUT: F0=0:interpret command/1:retern data used in Receive command/data
611 ; OUTPUT: F0=0(received)/1(not received)
612 ; DONE: a=0, F1=1, buffer rotate
613 X002c: clr f0 ; 002c - F0=0
614 X002d: jnt1 X0082 ; 002d - go to receive if T1(CLK)==L
615 sel rb1 ; 002f - switch to bank1
616 mov a,r5 ; 0030 - a=r5(bank1) r5(bank1): scan code buffer
617 sel rb0 ; 0031 - switch to bank0
618 jnz X0035 ; 0032 - jump if r5(bank1)!=0
619 retr ; 0034 - return if r5(bank1)==0 buffer empty
624 ; OUTPUT: F1=1:Sent,Rotate,Data ready/0:???
625 X0035: dec a ; 0035 - a--
627 call X00de ; 0037 - c=parity calc
628 jnt1 X0082 ; 0039 - go to receive if T1(CLK)=L
630 anl bus,#0bfh ; 003b - [CLK=L]
631 orl bus,#020h ; 003d - [DATA=H] [[[Start bit]]]
632 mov r0,#010h ; 003f - r0=10h
635 ; check inhibited(DATA==L) - check DATA line released by host
636 X0041: jni X0047 ; 0041 - jump if DATA==L LOOP>
637 jni X0049 ; 0043 - jump if DATA==L
638 jmp X0054 ; 0045 - cont. if DATA==H
639 X0047: jmp X0049 ; 0047 -
640 X0049: djnz r0,X0041 ; 0049 - <LOOP timeout?
642 orl bus,#040h ; 004b - [CLK=H]
643 anl bus,#0dfh ; 004d - [DATA=L] [[[idle state]]]
644 retr ; 004f - return send end(give up with inhibited)
647 ; check data==7eh Keep data in 'Resend' buffer unless it is 7eh
648 X0050: xrl a,#07eh ; 0050 - revert a
651 X0054: mov r0,#020h ; 0054 - r0=20h 'Resend' Buffer
652 xrl a,#07eh ; 0056 - a=a^7eh(0111 1110)
653 jz X0050 ; 0058 - jump if a==7eh
654 ; a!=7eh retain data to $20(resend buffer) if data is not 7eh
655 xrl a,#07eh ; 005a - revert a
656 mov @r0,a ; 005c - $20=a retain a to 'Resend' buffer
659 ; Data bit0-7 and Parity(c)
661 X005d: mov r7,#009h ; 005d - r7=9
662 X005f: mov r0,#009h ; 005f - r0=9 LOOP>>
663 jb0 X0069 ; 0061 - jump if a:bit0==1
666 anl bus,#0dfh ; 0063 - [DATA=L]
667 orl bus,#040h ; 0065 - [CLK=H]
671 X0069: orl bus,#020h ; 0069 - [DATA=H]
672 orl bus,#040h ; 006b - [CLK=H]
675 X006f: djnz r0,X006f ; 006f - 9*2cycle delay (around 60us??)
676 anl bus,#0bfh ; 0071 - [CLK=L]
677 rrc a ; 0073 - a=a>>1, c=a:bit0
678 djnz r7,X005f ; 0074 - <<LOOP
680 ; a=0, F1=1, buffer rotate
681 anl bus,#0dfh ; 0076 - [DATA=L] [Idle] End
684 cpl f1 ; 007a - F1=1 [Sent?]
685 orl bus,#040h ; 007b - [CLK=H] [Idle] End
686 ; remove from outgoing buffer: r7=0, r6=r7, r5=r6
687 sel rb1 ; 007d - switch to bank1
690 xch a,r5 ; 0080 - 0->r7->r6->r5->a [Bank1 Buffer rotate]
691 retr ; 0081 - retr reverts to bank0
696 ; Receive command/data from host
697 ; INPUT: F0=0:interpret command/1:return data(used by command)
698 ; OUTPUT: F0=0(received)/1(not received)
702 ; F1: 0: Receive or Send 1: Receive
704 X0082: jf1 X0086 ; 0082 - jump if F1==1
706 jmp X002d ; 0084 - Can't recevie, do 'Receive or Send' again
708 X0086: mov r0,#006h ; 0086 - r0=6h
709 X0088: djnz r0,X0088 ; 0088 - 6*2cycle dealy
710 jt1 X00cb ; 008a - return if T1(CLK)==H
711 anl bus,#0bfh ; 008c - [CLK=L]
712 orl bus,#020h ; 008e - [DATA=H] [Start bit]
713 mov r0,#011h ; 0090 -
714 X0092: djnz r0,X0092 ; 0092 - 11*2cycle delay
715 mov r7,#009h ; 0094 - r7=9h
716 X0096: orl bus,#040h ; 0096 - LOOP>[CLK=H] [Clock up for receive]
717 mov r0,#008h ; 0098 -
718 X009a: djnz r0,X009a ; 009a - 8*2cycle delay
719 anl bus,#0bfh ; 009c - [CLK=L] [Clock down]
720 jni X00a9 ; 009e - jump if INT(DATA)==L [Read bit] Read twice for debounce?
722 orl a,#001h ; 00a0 - a:bit0=1
723 jni X00ad ; 00a2 - jump if INT(DATA)==L
725 X00a4: rrc a ; 00a4 - a=a>>1 with carry [Next bit]
726 djnz r7,X0096 ; 00a5 - <LOOP
727 jmp X00b0 ; 00a7 - [go to Stop]
729 X00a9: anl a,#0feh ; 00a9 - a:bit0=0
730 jni X00a4 ; 00ab - jump if INT(DATA)==L
732 X00ad: clr f1 ; 00ad - F1=0 [Receive Error]
736 ; wait for Stop/ACK (DATA=H)
737 ; F0: 0=jump table, 1=return(with F0=0)
738 X00b0: orl bus,#040h ; 00b0 - [CLK=H] [Idle] End
739 mov r0,#004h ; 00b2 -
740 X00b4: djnz r0,X00b4 ; 00b4 - 4*2cycle? 8*0.2us=1.6us?
741 jni X00c7 ; 00b6 - jump if INT(DATA)==L [Stop Error] *no error response?
743 anl bus,#0dfh ; 00b8 - [DATA=L] [Idle] End
744 jf1 X00cc ; 00ba - jump if F1==1
745 ; F1==0 [Receive Error]
748 ; push 7eh into outgoing buffer (Receive Error at 00bah/Parity Error at 00ceh)
749 X00bc: mov a,#07eh ; 00bc - 7eh: error response
751 ; push data into top of outgoing buffer(Error response)
754 X00be: sel rb1 ; 00be - switch to bank1
756 xch a,r5 ; 00c0 - a->r5->r6->r7->a
759 jz X00cb ; 00c3 - jump if a==0
760 mov r7,#0ffh ; 00c5 - r7=ffh overflow [Over flow:FE]
762 X00c7: anl bus,#0dfh ; 00c7 - [DATA=L] [Idle] End
764 cpl f1 ; 00ca - F1=1 [Error flag]
769 ; check parity of recieve data
771 X00cc: call X00de ; 00cc - call parity calc
772 jc X00bc ; 00ce - jump if carryflag=1 (Parity ERROR)
774 jf0 X00dc ; 00d0 - jump if F0==1
781 cpl a ; 00d2 - compliment a ffh-a(command)
782 add a,#jump_table ; 00d3 - a=a+#jump_table
784 jmpp @a ; 00d7 - jump table [Keyboard command]
785 ; Command Out bound Error
786 X00d8: mov a,#0fdh ; 00d8 - error response: FD
792 X00dc: cpl f0 ; 00dc - F0=~F0(=0)
795 ; recieve data/command
796 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
800 ; calculate parity: 'c' depends on number of '1' in 'a'
802 ; OUTPUT: c(carry flag)
803 X00de: mov r0,#008h ; 00de - b8 08 8. r0=8h
804 X00e0: rr a ; 00e0 - 77 w a=a>>1
805 jb0 X00e4 ; 00e1 - 12 e4 .d jump if a:bit0==1
806 cpl c ; 00e3 - a7 ' compliment carry flag
807 X00e4: djnz r0,X00e0 ; 00e4 - e8 e0 h` jump if --r0!=0
813 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
815 ; Keyboard command jump table
817 ; jump_table:1 FE Resend(return content of $20)
818 X00e8: mov r0,#020h ; 00e8 - $20
819 mov a,@r0 ; 00ea - a=$20 get from resend buffer
820 jmp X00be ; 00eb - push into outogoing buffer
822 ; jump_table:2 FD r6=0bh, r4=r4|80h
823 mov r6,#00bh ; 00ed - r6=0bh BZ duration(scan cycles)?
824 orl bus,#080h ; 00ef - BZ=H(on)
826 orl a,#080h ; 00f2 - BZ=H
827 mov r4,a ; 00f4 - r4=r4|80h BZ=H(on) bus-default
831 mov r1,#01eh ; 00f6 - r1=1eh
837 ; FF: jump_table0 Soft Reset(008h)
838 ; FE: jump_table1 Resend(return content of $20)
839 ; FD: jump_table2 BZ set BZ=H(on) to bus and r4(bus-default), duration to r6
840 ; FC: jump_table3 Set key configuration
841 ; FB: jump_table4 Soft Reset(008h)
842 ; FA: jump_table5 Reset(000h)
844 jump_table: db 008h,0e8h,0edh,0f6h,008h,000h ; 00fa .hmv..
846 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
850 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
852 ; command FC parameter configuration
853 ; clear $22-3f, then set data received from host
859 ; F0=0 if data:bit7=1
860 ; F0=1 if data:bit7=0
864 ; FE Resend and receive again(011ah)
865 ; FF-80 F0=0 if bit7 of r7 is set
866 ; 7F-00 F0=1 if bit7 of r7 is reset
871 ; clear parameter configuration RAM $3f..22
874 X0100: clr a ; 0100 - a=0
875 mov r0,#03fh ; 0101 - r0=3f
876 X0103: mov @r0,a ; 0103 - $3f=a
878 djnz r1,X0103 ; 0105 -
879 call X01af ; 0107 - Read keyboar id and set parameter flags
880 call X0020 ; 0109 - r4=($21 & 07h | 50h) =52h
883 ; data receive from host
885 X010b: clr f0 ; 010b - LOOP>>
887 X010d: call X002d ; 010d - receive/send data with F0=1
888 jf0 X010d ; 010f - LOOP while F0==1
891 ; received data from host(F0==0)
892 mov r7,a ; 0111 - r7=data received
898 jz X013b ; 0114 - return if a==FF
900 jnz X011e ; 0118 - jump if a!=FE
904 call X00e8 ; 011a - Resend and continue...
905 jmp X010b ; 011c - <<LOOP Send/Receive loop again
909 ; data:bit7=1:enable break/0:enable repeat
910 X011e: mov a,r7 ; 011e - a=r7(data received)
911 jb7 X0122 ; 011f - jump if a:bit7==1 (1xxx xxxx)
912 cpl f0 ; 0121 - F0=~F0=1 if a:bit7==0 [F0=1 means data:bit7==0]
913 X0122: anl a,#07fh ; 0122 - a=a&7fh [data:bit6-0=scan code]
914 mov r7,a ; 0124 - r7=a
917 ; identify keybaord from $21=keyboar identity bits
918 mov r1,#021h ; 0125 - r1=21h
919 mov a,@r1 ; 0127 - a=($21)
920 anl a,#0f0h ; 0128 - a=a&f0h
921 xrl a,#020h ; 012a - a=a^20h
922 jz X013c ; 012c - jump if $21==0010 xxxx 6019273 50-key?
923 xrl a,#010h ; 012e - a=a^10h
924 jz X0142 ; 0130 - jump if $21==0011 xxxx *6019284 62-key*
925 xrl a,#070h ; 0132 - a=a^70h
926 jz X0148 ; 0134 - jump if $21==0100 xxxx 6019303 77-key?
929 mov a,r7 ; 0136 - a=r7(received data)
930 call X015f ; 0137 - [Set flag]
931 jmp X010b ; 0139 - <<LOOP receive again
938 ; Set 'index' and 'size' scan code table for each keyboard model
939 ; r1: end of scan code table(index)
940 ; r2: number of scan code table(size)
942 X013c: mov r1,#0afh ; 013c - r1=afh address@page3 03afh(table1)
943 mov r2,#038h ; 013e - r2=38h 0011 10(00) 56keys
947 X0142: mov r1,#0efh ; 0142 - r1=efh address@page3 03efh(table2)
948 mov r2,#040h ; 0144 - r2=40h 0100 00(00) 64keys
952 X0148: mov r1,#0ffh ; 0148 - r1=ffh address@page3 03ffh(table2)
953 mov r2,#050h ; 014a - r2=50h 0101 00(00) 80keys
957 ; get scancode from table and test loop
959 X014c: mov a,r1 ; 014c - a=r1
960 movp3 a,@a ; 014d - a=(r1) read scan code table
961 xrl a,r7 ; 014e - a=a^r7 a==r7(received scan code)
964 ; scan code(a) == received data(r7)
966 mov a,r2 ; 0152 - a=r2
967 call X015f ; 0153 - call [Set flag]
970 ; check next scan code
971 X0156: dec r1 ; 0156 - r1-- r1: address of table
972 djnz r2,X014c ; 0157 - <<LOOP while --r2 r2: number of table
974 jnc X015d ; 0159 - jump if r1>=0
975 call X00d8 ; 015b - Error: FD and cont. [Out of bound Error: FD]
976 X015d: jmp X010b ; 015d - <<LOOP Receive next data
980 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
983 ; INPUT: a=table index(number of table)
984 ; a: AAAA AAFF(AAAAAA:index of parameter RAM, FF: flag position(0-3))
986 X015f: clr c ; 015f - c=0
987 ; calculate RAM address
988 mov r2,a ; 0160 - r2=a r2=data
990 rr a ; 0162 - a=a>>1 a/4(four keys per a parameter byte)
991 add a,#022h ; 0163 - a=a+22h start of parameter bytes
992 mov r0,a ; 0165 - r0=a r0=parameter address
994 mov a,r2 ; 0166 - a=r2
995 anl a,#003h ; 0167 - a=a&03h [a=flag position]
996 jz X017e ; 0169 - if FF==0b00
998 jz X018a ; 016c - if FF==0b01
1000 jz X0197 ; 016f - if FF==0b10
1003 ; Parameter byte and configure flags
1004 ; bit 7 6 5 4 3 2 1 0
1005 ; 3r 3b 2r 2b 1r 1b 0r 0b
1009 mov a,@r0 ; 0171 - a=(r0) r0=parameter address
1010 anl a,#03fh ; 0172 - a=a&0011 1111b clear 3r/3b
1011 jf0 X017a ; 0174 - jump if F0==1
1012 ; F0==0(received data:bit7==1)
1014 orl a,#040h ; 0176 - a=a|0100 0000b 3b: break enabled
1019 ; store to RAM and return
1020 X0178: mov @r0,a ; 0178 - (r0)=a store parameter to RAM
1021 ret ; 0179 - return a: command/received data
1027 ; F0==1 (data:bit7==0)
1029 X017a: orl a,#080h ; 017a - a=a|1000 0000b 3r: repeat enabled
1036 X017e: mov a,@r0 ; 017e - a=(r0)
1037 anl a,#0fch ; 017f - a=a & 1111 1100b clear 0r/0b
1038 jf0 X0186 ; 0181 - jump if F0==1
1039 ; F0==0(data:bit==1)
1040 inc a ; 0183 - a++ 0b: break enabled
1042 ; F0==1(data:bit==0)
1043 X0186: orl a,#002h ; 0186 - 0r: repeat enabled
1050 X018a: mov a,@r0 ; 018a -
1051 anl a,#0f3h ; 018b - clear 1r/1b
1053 ; F0==0(data:bit==1)
1054 orl a,#004h ; 018f - 1b: break enabled
1056 ; F0==1(data:bit==0)
1057 X0193: orl a,#008h ; 0193 - 1r: repeat enabled
1063 ; FF==10b parameter|10h / parameter|20h
1064 X0197: mov a,@r0 ; 0197 -
1065 anl a,#0cfh ; 0198 - clear 2r/2b
1067 ; F0==0(data:bit==1)
1068 orl a,#010h ; 019c - 2b: break enabled
1070 ; F0==1(data:bit==0)
1071 X01a0: orl a,#020h ; 01a0 - 2r: repeat enabled
1079 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1084 ; read program memory @page1
1085 ; INPUT: a=address of program memory
1086 X01a4: movp a,@a ; 01a4 - a=(a)@page1
1088 ; OUTPUT: r1=r1+a, a=r0
1090 X01a5: add a,r1 ; 01a5 -
1091 mov r1,a ; 01a6 - r1=a+r1
1092 mov a,r0 ; 01a7 - a=r0
1097 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1099 ; Scan row8(I) and set parameter flags(on Power on Reset)
1101 ; call from hard reset 0018h with a=0, r0=0, r1=0?
1102 ; INPUT: r0, r1: for wait loop
1103 ; OUTPUT: $21=keybaord identity bits, r4=$21&f0h
1107 ; delay to make Buzzer audible when powering up??
1108 X01a9: djnz r0,X01a9 ; 01a9 - r0*2cycle
1109 djnz r1,X01a9 ; 01ab - r1*(r0*2cycle+2cycle) 256*(256*2+2)=131584(2us?/cycle) around 260ms??
1110 anl bus,#0c0h ; 01ad - BZ=_,CLK=_,DATA=L line is idle
1115 ; Read keyboard identity bits from row8(I) and set parameter flags(on command FC)
1117 ; OUTPUT: r4=a=scanned data of row8(I)=keyboard identity bits
1119 ; F0: 1:read(frist)/0:read(second)&settle
1120 ; It needs to read same value twice to settle.
1122 ; Keyboar id bit pattern on PCB:
1125 ; Sensor value meaning:
1127 ; Kbd id: 1(mark) 0(blank)
1128 ; Key: 1(pressed) 0(released)
1130 ; called from command FC 0107h
1131 X01af: mov r7,#008h ; 01af - r7=08h [column]
1132 X01b1: rl a ; 01b1 - a=a<<1 LOOP_0{ [next column]
1133 X01b2: mov r4,a ; 01b2 - LOOP{ r4=a [data]
1134 cpl f0 ; 01b3 - F0=~F0 toggle F0 [read twice to debounce]
1135 mov a,r7 ; 01b4 - a=r7
1137 orl a,#0c0h ; 01b6 - col(7-0)|c0h = c7-c0h BZ=H:on [Beep during FC command]
1138 outl bus,a ; 01b8 - [Select column]
1139 orl bus,#010h ; 01b9 - D4=1 [charge sensor out=H?]
1140 mov a,#0d2h ; 01bb - 1101 0010
1141 outl bus,a ; 01bd - bus=d2h D4-0=10010 select column 2?
1144 orl p2,#001h ; 01be - P2:0=1 [select row8(I)]
1145 mov a,r4 ; 01c0 - a=r4(data)
1146 orl bus,#008h ; 01c1 - bus=d2h|08h=dah D4=1 [Strobe?](1101 1010)
1147 anl p2,#000h ; 01c3 - P2:0=L [unselect row8(I)]
1149 ; check sensor out(T0)
1150 jt0 X01d5 ; 01c5 - jump if T0==H
1151 jf0 X01cd ; 01c7 - jump if F0==1
1152 jb0 X01d9 ; 01c9 - jump if a:bit0==1 [Settle]
1153 ; TO(sensor)==0 && F0==0 && a:bit0==0
1154 jmp X01b2 ; 01cb - }LOOP
1156 ; record 1(a=a|01h) when key is on(T0=L) and F0==1
1157 ; T0(sensor)==L(off) && F0==1 (from 01c7)
1158 X01cd: orl a,#001h ; 01cd - a=a|1 [Set a:bit0=H]
1159 jmp X01b2 ; 01cf - LOOP
1161 ; record 0(a=a&feh) when key is off(T0=H) and F0==0
1162 ; T0(sensor)==H(on) && F0==0 && a:bit0==1(off) (from 01d7)
1163 X01d1: anl a,#0feh ; 01d1 - a=a&feh [Set a:bit0=L]
1164 jmp X01b2 ; 01d3 - LOOP
1167 ; T0(sensor)==H(on) && F0==1 (from 01c5)
1168 X01d5: jf0 X01b2 ; 01d5 - LOOP while F0==1
1170 ; T0(sensor)==H(on) && F0==0
1171 jb0 X01d1 ; 01d7 - jump if a:bit0==1 [need to change r4(a) to 0]
1174 ; T0(sensor)==H && F0==0 && a:bit0==0 OR
1175 ; T0(sensor)==L && F0==0 && a:bit0==1 (from 01c9)
1176 X01d9: djnz r7,X01b1 ; 01d9 - }LOOP_0 while --r7>0 [Next column]
1177 mov r4,a ; 01db - r4=a a=r4=scanned data of Row8(I)
1181 ; Set parameters from scanned data of row 8(I)
1183 ; INPUT: a=r4=keyboard identity bits
1184 ; OUTPUT: $21=keybaord identity bits, r4=$21&f0h
1186 anl a,#0f0h ; 01dc - a=a&f0h
1187 xrl a,#020h ; 01de - a=a^20h (a==0010 xxxx) 6019273
1188 jz X01ec ; 01e0 - jump if a==0
1189 xrl a,#010h ; 01e2 - a=a^10h (a==0011 xxxx) *6019284 when power on reset
1190 jz X01f2 ; 01e4 - jump if a==0
1191 xrl a,#070h ; 01e6 - a=a^70h (a==0100 xxxx) 6019303
1192 jz X01f2 ; 01e8 - jump if a==0
1195 ; $21==(0010 xxxx) for 6019273(50-key)
1196 ; set break enalbe flag for Reset(or on other layout?)
1197 X01ec: mov r0,#022h ; 01ec -
1198 mov @r0,#001h ; 01ee - $22=1 $22:bit0=break enable falg of ????
1201 ; $21==(0011 0010 | 0100 xxxx) for 6019284(62-key) or 6019303(77-key) layout
1202 ; set break enable flag for LAlt and RAlt *6019284
1203 X01f2: mov r0,#02eh ; 01f2 -
1204 mov @r0,#001h ; 01f4 - $2e=1 $2e:bit0=break enable flag of LAlt
1205 mov r0,#024h ; 01f6 -
1206 mov @r0,#001h ; 01f8 - $24=1 $24:bit0=break enable flag of RAlt
1208 ; set $21 to scanned data of row 8(I) [keyboard identity bits]
1209 X01fa: mov r0,#021h ; 01fa -
1211 mov @r0,a ; 01fd - ($21)=r4 $21: r4=identity bits(row 8(I))
1212 anl a,#0f0h ; 01fe -
1213 mov r4,a ; 0200 - r4=r4&f0h
1216 ; End of Scan row8(I)
1217 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1220 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1222 ; Test and clear memory(3fh..00h) on Power on Reset
1224 X0202: mov r0,#03fh ; 0202 - $3f
1225 X0204: mov a,@r0 ; 0204 - LOOP>>
1226 mov r1,a ; 0205 - r1=(r0) r0=3f..00
1227 mov a,#0ffh ; 0206 - a=ffh
1228 mov @r0,a ; 0208 - (r0)=ffh
1229 xrl a,@r0 ; 0209 - a=a^ffh =0??
1230 jnz X0224 ; 020a - jump if a!=ffh *always should be a=zero*
1231 mov @r0,a ; 020c - (r0)=a (=0)
1232 mov a,@r0 ; 020d - a=(r0)
1233 jnz X0224 ; 020e - jump if a!=ffh *always should be a=zero*
1234 mov a,r1 ; 0210 - a=r1
1235 mov @r0,a ; 0211 - (r0)=a (revert to origin value)
1236 djnz r0,X0204 ; 0212 - <<LOOP --r0
1239 ; Test program memory(0,255..1 @page0,1,2,3)
1242 ; OUTPUT: r4=$21&07h|50h, a=swapHL(r4(original)) or feh
1243 X0214: mov a,r0 ; 0214 - LOOP>> a=r0=0
1244 call X0029 ; 0215 - r1=r1+(a), a=r0 (page0)
1245 call X01a4 ; 0217 - r1=r1+(a), a=r0 (page1)
1247 call X01a5 ; 021a - r1=r1+(a), a=r0 (page2)
1249 call X01a5 ; 021d - r1=r1+(a), a=r0 (page3)
1250 djnz r0,X0214 ; 021f - <<LOOP --r0
1251 mov a,r1 ; 0221 - a=r1 sum of program memory data
1252 jz X0226 ; 0222 - sum of program memory data != 0 if no error ???
1254 ; Send FE on error and r4 on success
1255 X0224: mov r4,#0efh ; 0224 - r4=efh Memory error
1256 X0226: call X0020 ; 0226 - r4=$21&07h|50h, a=r4(keyboard id or efh)
1257 swap a ; 0228 - swap a:h<->a:l
1258 orl a,#0a0h ; 0229 - a=a|a0h(1010 iiii) i:keyboard id(hi-bits)
1259 call X0339 ; 022b - queue data(a) to buffer
1260 call X010b ; 022d - send kbd ID and wait for data from host [FC command]
1261 strt t ; 022f - start timer
1262 ; Usually first data form keyboard at startup is A3h(sum of program memory?).
1263 ; FEh for memory error??
1264 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1268 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1272 ; check scan code buffer to send
1273 X0230: call X002c ; 0230 - receive/send data
1274 mov a,r6 ; 0232 - a=r6 set by command FD Short Beep(0bh at 00edh)
1276 djnz r6,X023d ; 0235 - r6--
1278 anl bus,#07fh ; 0237 - BZ=L(off) when get to r6==0 [Short Beep ends]
1280 anl a,#07fh ; 023a -
1281 mov r4,a ; 023c - r4=r4&7fh(BZ=L:off) r4=bus-default
1283 ; delay for scan 192*32cycle?
1284 X023d: mov a,t ; 023d - a=t(timer)
1285 add a,#064h ; 023e - a=a+64h
1286 jnc X023d ; 0240 - delay for scan
1288 mov t,a ; 0243 - t=0 timer clear
1292 X0244: mov a,r4 ; 0244 - a=r4
1293 anl a,#0c0h ; 0245 - a=a&c0h BZ=_,CLK=_,DAT=L:
1294 mov r7,a ; 0247 - r7=r4&c0h r7=bus-current
1295 jf1 X0253 ; 0248 - jump if F1==1 (p1/p2)
1298 cpl f1 ; 024a - F1=1(=~F1)
1299 mov r2,#03fh ; 024b - r2=3fh scan code seed
1300 mov r3,#001h ; 024d - r3=01h row mask
1301 mov r1,#015h ; 024f - r1=15h last key state
1302 jmp X0263 ; 0251 - scan matrix p1 row
1305 X0253: clr f0 ; 0253 - F0=0
1306 clr f1 ; 0254 - F1=0
1307 mov r2,#077h ; 0255 - r2=77h scan code seed
1308 mov r3,#002h ; 0257 - r3=02h
1309 mov r1,#01ch ; 0259 - r1=1ch last key state
1310 jmp X0287 ; 025b - Scan matrix p2 row
1313 X025d: cpl f1 ; 025d - F1=~F1=1
1314 call X002c ; 025e - receive/send data
1315 clr f1 ; 0260 - F1=0
1318 ;;;;;;;;;;;;;;;;;;;;;;;;;;;
1320 ; scan matrix p1 row
1321 ; INPUT: F1=1, r1=15h, r2=3fh, r3=01h, r7=r4&c0h
1324 ; r0:col, r7:bus-current, r3:row(drive H), r4=bus-default
1330 X0263: mov a,#008h ; 0263 - a=8 LOOP>>>
1331 mov r0,a ; 0265 - r0=08h =column
1332 orl a,r7 ; 0266 - a=08h|r7
1333 mov r7,a ; 0267 - r7=a =xxxx 1ccc(G:1 column:ccc) r7=P1 value
1334 X0268: dec r7 ; 0268 - LOOP>> r7--
1335 mov a,r7 ; 0269 - a=r7
1336 outl bus,a ; 026a - [select column]
1337 orl bus,#010h ; 026b - sensor out=H [sensor clamp=H]???
1338 mov a,r3 ; 026d - a=r3 current row
1339 outl p1,a ; 026e - drive line with H [select row]
1340 mov a,r4 ; 026f - a=r4 bus default value
1341 outl bus,a ; 0270 - [revert bus default]
1342 orl bus,#008h ; 0271 - D3:H sensor-G [strobe]??? hold? clean Sensor?
1343 anl p1,#000h ; 0273 - [unselect row]
1345 jnt0 X02ab ; 0275 - sensor out==0
1346 ; Sensor==1[key is on]
1347 mov a,@r1 ; 0277 - a=$(r1); r1=15... last key state
1348 jb7 X02e5 ; 0278 - jump if a:bit7==1(off) press
1349 ; a:bit7==0(last key state is on) same as last
1354 X027a: rl a ; 027a - a=a<<1
1355 mov @r1,a ; 027b - (r1)=a; (r1)=(r1)<<1 next col of last key state
1356 X027c: dec r2 ; 027c - r2-- [key index of scan code table]
1357 djnz r0,X0268 ; 027d - <<LOOP(8) [next col]
1359 dec r1 ; 027f - r1-- 15,14,13,12,11,10,0F,0E? [last key state]
1362 mov r3,a ; 0282 - r3=r3<<1 next row
1363 jb0 X0230 ; 0283 - jump if a:bit0==1 scan end(goto Main loop)
1364 jmp X0263 ; 0285 - <<<LOOP [next row]
1367 ;;;;;;;;;;;;;;;;;;;;;;;;;;;
1369 ; Scan matrix p2 row(F1==1)
1370 ; INPUT: F0=0, F1=0, r1=1ch, r2=77h, r3=02h, r7=bus-current, r4=bus-default
1372 ; r0:col, r7:bus-current, r3:row(drive H), r4=bus-default
1374 X0287: mov a,#008h ; 0287 - a=8 LOOP>>
1375 mov r0,a ; 0289 - r0=8
1376 orl a,r7 ; 028a - a=a|r7
1377 mov r7,a ; 028b - r7=a
1378 X028c: dec r7 ; 028c - r7-- LOOP>>
1379 mov a,r7 ; 028d - a=r7
1380 outl bus,a ; 028e - [select column]
1381 mov a,r4 ; 0293 - bus default value
1382 outl bus,a ; 0294 - [revert bus default]
1383 orl bus,#008h ; 0295 - [strobe]
1384 anl p2,#000h ; 0297 - p2=00h [unselect row]
1385 jnt0 X02ab ; 0299 - jump if sensor out==0(key is on)
1386 ; sensor==1(key is off)
1387 mov a,@r1 ; 029b - a=(r1) [last key state]
1388 jb7 X02e5 ; 029c - jump if a:bit7==1(off) press
1390 ; a:bit7==0(last key state is on)
1391 X029e: rl a ; 029e - a=a<<1
1392 mov @r1,a ; 029f - (r1)=a [next last key bit]
1393 X02a0: dec r2 ; 02a0 - r2--(77h)
1394 djnz r0,X028c ; 02a1 - jump if r0--!=0 <<LOOP(8)
1395 dec r1 ; 02a3 - r1-- [next last key byte]
1398 mov r3,a ; 02a6 - r3=r3<<1 [next row]??
1400 jmp X0287 ; 02a9 - <<LOOP
1403 ; debouncing and change last key state
1405 ; sensor out==0(press; key is on)
1408 X02ab: call X030d ; 02ab - a=0(sensor out=1), ffh(sensor out=0) [Sense key]
1409 jz X02f8 ; 02ad - if a==0(key is off)
1410 call X030d ; 02af - [Sense key]
1411 jz X02f8 ; 02b1 - if a==0(key is off)
1413 ; Sensor==0(a=ffh; press)
1414 mov a,@r1 ; 02b3 - a=(r1) last key state????
1418 ; [release](off->on)
1420 ; last:bit7==0(off) && sensor=0(on)
1421 orl a,#080h ; 02b6 - 0:on 1:off
1423 mov @r1,a ; 02b9 - (r1)=(r1)<<1 next column
1424 call X0325 ; 02ba - key configure flag
1425 ; (a:bit1=repeat enable, a:bit0=break enable)
1426 ; if keyconf:bit0==1 then set release flag
1427 jb0 X02fd ; 02bc - r2=r2|80h [press flag]
1428 ; if keyconf:bit1==1 then set repeat
1429 jb1 X02e1 ; 02be - r5=repeat delay [repeat]
1431 ; get scan code and queue it into buffer
1432 X02c0: call translate034E ; 02c0 - a=scancode
1433 call X0339 ; 02c2 - queue data to buffer
1434 call X0303 ; 02c4 - [r1=a=address of last key state]
1435 X02c6: jf1 X027c ; 02c6 - next col(F1==1)
1436 jmp X02a0 ; 02c8 - next col(F1==0)
1441 ; last key is on and sensor==0(on) (on->on)
1442 X02ca: rl a ; 02ca -
1443 mov @r1,a ; 02cb - (r1)=(r1)<<1
1444 call X0325 ; 02cc - key configure flag
1445 ; (a:bit1=repeat enable, a:bit0=break enable)
1447 jb1 X02d4 ; 02ce - [repeat]
1449 ; if repeat:flag(bit1)==0 (no repeat)
1450 X02d0: call X0303 ; 02d0 - r1=r2&0fh+0eh address of last key state
1451 jmp X02c6 ; 02d2 - goto next col
1453 ; if flag:bit1==1 (repeat)
1454 X02d4: jf0 X02dd ; 02d4 -
1457 cpl f0 ; 02d6 - F0=~F0=1
1458 djnz r5,X02d0 ; 02d7 -
1459 mov r5,#007h ; 02d9 - r5=07h repeat interval
1460 jmp X02c0 ; 02db - send scan code
1463 X02dd: mov r5,#028h ; 02dd - r5=28h repeat delay(for first repeat)
1466 X02e1: mov r5,#028h ; 02e1 - r5=28h repeat delay(for first repeat)
1467 jmp X02c0 ; 02e3 - send scan code
1471 ; debouncing and change last key state: press
1473 ; INPUT: (r1): last key status
1475 ; (r1):bit7==1(last key is on) && Sensor==1(key is off) [release]
1476 X02e5: call X030d ; 02e5 - a=0(sensor out=1), ffh(sensor out=0) [Sense key]
1478 call X030d ; 02e9 - [Sense key]
1479 jnz X02f8 ; 02eb - \_debouncing
1480 ; Sensor==1(a=0) [Debounced]
1485 mov a,@r1 ; 02ed - a=(r1) RAM
1486 anl a,#07fh ; 02ee - a=a&7fh last state=0(0:on 1:off)
1487 rl a ; 02f0 - a=a<<1
1488 mov @r1,a ; 02f1 - (r1)=a
1490 call X0325 ; 02f2 - key configure flag
1491 ; (a:bit1=repeat enable, a:bit0=break enable)
1492 jb0 X02c0 ; 02f4 - goto translate if a:bit0==1
1495 ; go to next col scan Sensor==1
1496 X02f8: mov a,@r1 ; 02f8 -
1497 jf1 X027a ; 02f9 - goto next col scan(p1) if F1==1 [Next column]
1498 jmp X029e ; 02fb - goto next col scan(p2) else [Next column]
1501 ; add press flag(bit8)
1503 X02fd: mov a,r2 ; 02fd - [key index]
1504 orl a,#080h ; 02fe -
1505 mov r2,a ; 0300 - r2=r2|80h **press flag**
1508 ; Address of last key state
1509 ; INPUT: r2=key index
1510 ; OUTPUT: r1=(r2>>3)&0fh+0eh = address of last key state
1511 X0303: mov a,r2 ; 0303 - a=r2 key index
1514 rr a ; 0306 - a= a>>3
1515 anl a,#00fh ; 0307 - a= a & 0fh
1516 add a,#00eh ; 0309 - a= a + 0eh
1517 mov r1,a ; 030b - r1=a
1520 ;;;;;;;;;;;;;;;;;;;;;;;
1522 ; INPUT: r7: bus-current, F1:0(p2),1(p1) r4=bus-default, r3=row
1523 ; RETURN: a=0xff(sensor out=0, press), 0(sensor out=1, release)
1525 X030d: mov a,r7 ; 030d - r7: bus-current
1526 outl bus,a ; 030e - [Select column]
1527 orl bus,#010h ; 030f - [Charge: D4]
1528 mov a,r3 ; 0311 - r3: row(drive) select p1(F1=1)/p2(F1=0) setting
1531 outl p2,a ; 0314 - set p2 [Select row]
1534 X0317: outl p1,a ; 0317 - set p1 [Select row]
1536 X0318: mov a,r4 ; 0318 - r4: bus-default
1537 outl bus,a ; 0319 - set bus
1539 orl bus,#008h ; 031b - [Strobe: D3]
1540 anl p1,#000h ; 031d - clear p1 [Unselect row]
1541 anl p2,#000h ; 031f - clear p2 [Unselect row]
1543 jt0 X0324 ; 0321 - sensor out==1
1545 cpl a ; 0323 - a=0xff [press(on)]
1547 X0324: ret ; 0324 - a=0 [release(off)]
1551 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1555 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1557 ; key configure flags
1559 ; INPUT: r2=key index(p1:-3fh, p2:-77h) (aaaaaaii)
1560 : OUTPUT: a=Key configure 2-bit flags; bit0 and 1 are only valid. (------rb)
1562 : Key configure flags are retained in RAM($22-3F) and
1563 ; Key configure flags use 2bit per key so that a byte can has flags of four key like:
1564 ; bit 7 6 5 4 3 2 1 0
1565 ; 3r 3b 2r 2b 1r 1b 0r 0b
1566 ; where r=repeat enable, b=break code(release) eanble
1568 X0325: mov a,r2 ; 0325 - a=r2 index
1570 rr a ; 0327 - a=a>>2 bit7-2 of index(aaaaaa)
1571 add a,#022h ; 0328 - a=a+22h $22+aaaaaa
1572 mov r1,a ; 032a - r1=a
1573 mov a,@r1 ; 032b - a=(r1) $22-3F(ignored bit7,bit6)
1574 mov r1,a ; 032c - r1=a r1=($22-3F) ????
1575 mov a,r2 ; 032d - a=r2 index
1576 anl a,#003h ; 032e - a=a&03h a=bit0,bit1 of index
1577 xch a,r1 ; 0330 - a<->r1 r1=bit0,bit1 of index, a=($22-3F)
1578 inc r1 ; 0331 - r1++ =1-4
1579 X0332: djnz r1,X0335 ; 0332 - while --r1>0
1582 ; place flags of the key on bit0 and 1
1583 X0335: rr a ; 0335 -
1584 rr a ; 0336 - a=a>>2; a=$22-3F
1588 ; Queue data to bottom of outgoing buffer(bank1:r5,r6,r7)
1589 ; INPUT: a=data, r2=???
1592 X0339: sel rb1 ; 0339 - switch to bank1
1594 xch a,r5 ; 033b - a<->r5
1602 mov r7,#0ffh ; 0346 - buffer overflow
1603 X0348: sel rb0 ; 0348 - switch to bank0
1604 mov a,r2 ; 0349 - a=r2
1605 anl a,#07fh ; 034a - a=a&7fh
1606 mov r2,a ; 034c - r2=a
1609 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1613 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1615 ; Translate key index into scancode
1617 ; INPUT: r2=keyindex [bit7:release flag(1:release/0:press), bit6-0:index]
1618 ; OUTPUT: a=scancode
1620 mov r1,#021h ; 034e -
1621 mov a,@r1 ; 0350 - a=$21 $21:bit6,5,4 = traslate table
1622 anl a,#0f0h ; 0351 - a=a & f0h
1623 xrl a,#020h ; 0353 - a=a ^ 20h $21:bit5(0010 0000) 0010 xxxx => table1
1624 jz X0361 ; 0355 - if a==0 read table1 (6019273 50-key)
1625 xrl a,#010h ; 0357 - a=a ^ 10h $21:bit4(0001 0000) 0011 xxxx => table2
1626 jz X0370 ; 0359 - read table2 (6019284 62-key)
1627 xrl a,#070h ; 035b - a=a & 70h $21:bit6(0111 0000) 0100 xxxx => table2
1628 jz X0370 ; 035d - read table2 (6019303 77-key)
1629 mov a,r2 ; 035f - else use r2(keyindex) instead of scancode
1632 X0361: mov a,r2 ; 0361 - keyindex
1633 anl a,#07fh ; 0362 -
1634 add a,#078h ; 0364 - table1
1636 X0366: movp3 a,@a ; 0366 - read scancode from table a=scan code
1637 xch a,r2 ; 0367 - a=keyindex, r2=scancode
1638 jb7 X036c ; 0368 - if keyindex:bit7==1 [relase event]
1639 xch a,r2 ; 036a - a=scancode, r2=keyindex
1642 X036c: xch a,r2 ; 036c -
1643 orl a,#080h ; 036d - [[[[[release flag(bit7)]]]]]
1644 ret ; 036f - a: scan code
1646 X0370: mov a,r2 ; 0370 -
1647 anl a,#07fh ; 0371 -
1648 add a,#0b0h ; 0373 - table2
1649 jmp X0366 ; 0375 - read table
1652 ; maybe 'salt' to make sum of program memory 'zero'(at 0222h)
1662 ; Used for 6019273 Add Key Parameter RAM
1663 table1: db 03fh,037h,03ah,036h,02ah,035h,022h,023h ; 0378
1664 db 03bh,02bh,039h,031h,032h,029h,021h,0ffh ; 0380
1665 db 033h,038h,0ffh,030h,028h,0ffh,020h,0ffh ; 0388
1666 db 017h,01dh,01ch,015h,00ch,00dh,004h,005h ; 0390
1667 db 00fh,01fh,01bh,013h,014h,00bh,003h,0ffh ; 0398
1668 db 00eh,01ah,019h,012h,009h,00ah,001h,002h ; 03a0
1669 db 016h,01eh,018h,010h,011h,008h,000h,0ffh ; 03a8
1672 ; Used for 6019284 and 6019303 Add Key Parameter RAM
1673 table2: db 02fh,03dh,03ch,02dh,01dh,01ch,00ch,00eh ; 03b0 Enter ... BS $22, $23
1674 db 03fh,042h,03bh,02bh,02ch,01bh,01fh,00dh ; 03b8 RAlt ... $24, $25
1675 db 039h,03ah,029h,02ah,002h,003h,00ah,00fh ; 03c0 ... $26, $27
1676 db 038h,037h,028h,027h,017h,001h,008h,009h ; 03c8 ... $28, $29
1677 db 040h,036h,025h,026h,015h,016h,011h,012h ; 03d0 ... $2a, $2b
1678 db 035h,034h,023h,024h,013h,014h,01ah,010h ; 03d8 ... $2c, $2d
1679 db 03fh,032h,033h,022h,021h,006h,005h,019h ; 03e0 LAlt ... $2e, $2f
1680 db 031h,041h,03eh,030h,020h,004h,000h,018h ; 03e8 Reset ... 1 $30, $31
1681 db 071h,076h,075h,066h,055h,056h,045h,046h ; 03f0 Used for 77-key $32, $33
1682 db 077h,067h,074h,064h,065h,054h,0ffh,044h ; 03f8 Used for 77-key $34, $35
1684 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1691 ; these are symbols from the control
1692 ; file that are referenced in the code