]> git.friedersdorff.com Git - max/tmk_keyboard.git/commitdiff
ibm4704_usb: Update document
authortmk <hasu@tmk-kbd.com>
Fri, 12 Jul 2019 18:02:38 +0000 (03:02 +0900)
committertmk <hasu@tmk-kbd.com>
Fri, 12 Jul 2019 18:02:38 +0000 (03:02 +0900)
converter/ibm4704_usb/ibm4704.txt

index 73c8a3b9ff2bf3a1fc014237e91ff97675ab1555..3e983848d3b5e42670e8b9319da72a0daf6eabd4 100644 (file)
@@ -1,3 +1,7 @@
+IBM 4704 Keyboard Analysis - 6019284(62-key)
+============================================
+2013/02/09, 2019/07/12
+
 IBM 4704 Keyboard
 =================
 IBM capacitive switch models:
@@ -12,22 +16,26 @@ Alps switch(vintage Green) models:
     6112884 Japanese 102-key    http://geekhack.org/index.php?topic=50437.msg1193047#msg1193047
     6341739 Chinese 102-key     http://geekhack.org/index.php?topic=52888.msg1176566#msg1176566
 
+
+
 Resourse
 --------
 The IBM 4704: lots of pictures and info
-http://kishy.dyndns.org/?p=648#more-648 
+http://kishy.ca/?p=894
+http://imgur.com/a/LaABs
 
 Brochure:
 http://ed-thelen.org/comp-hist/IBM-ProdAnn/4700.pdf
 
 
 
-IBM 4704 Keyboard Protocol
-==========================
+4704 Keyboard Protocol
+======================
 On powering up keyboard sends keyboard ID; A3h for 6019284(62-key), for example.
 After that the keyboard enters FC command mode and waits for parameter data from host
 so that it doesn't send any scancode until you send 'FF'(End of FC command mode).
 
+
     Keyboard                    ID
     -------------------------------
     Model 100 50-key            A2h
@@ -59,7 +67,7 @@ Data bits are LSB first and Pairty is odd. Clock has around 60us high and 30us l
 
             ____       __   __   __   __   __   __   __   __   __   _______
     Clock       \_____/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/
-                 ____ ____ ____ ____ ____ ____ ____ ____ ____ ____    
+                 ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
     Data    ____/    X____X____X____X____X____X____X____X____X____X________
                 Start   0    1    2    3    4    5    6    7    P  Stop
 
@@ -69,6 +77,7 @@ Timing:     Host reads bit while Clock is hi.(rising edge)
 Stop bit:   Keyboard pulls down Data line to lo after 9th clock.
 
 
+
 Host to Keyboard
 ----------------
 Data bits are LSB first and Pairty is odd. Clock has around 60us high and 30us low part.
@@ -80,7 +89,7 @@ Data bits are LSB first and Pairty is odd. Clock has around 60us high and 30us l
                 |  Start   0    1    2    3    4    5    6    7    P   Stop
                 Request by host
 
-Start bit:  can be long as 300-350us.
+Start bit:  can be long as 300-350us during start up and upto 2500us while key scanning
 Request:    Host pulls Clock line down to request to send a command.
 Timing:     After Request keyboard pull up Data and down Clock line to low for start bit.
             After request host release Clock line once Data line becomes hi.
@@ -88,19 +97,20 @@ Timing:     After Request keyboard pull up Data and down Clock line to low for s
 Stop bit:   Host releases or pulls up Data line to hi after 9th clock and waits for keybaord pull down the line to lo.
 
 
+
 Scancodes
 ---------
 Keyboard doesn't send Break code for all keys except for Alt by default.
 
     6019284 62-key:
     ,-----------------------------------------------------------.
-    |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|???|BS |
+    |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|**1|BS |
     |-----------------------------------------------------------|
     |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P| ¢|  \|  PD2|
     |-----------------------------------------------------------|
     |Ctrl  |  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '| {}| PD3|
     |-----------------------------------------------------------|
-    |Shif| <>|  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|???|Shift |
+    |Shif| <>|  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|**2|Shift |
     |-----------------------------------------------------------|
     |Reset|blk|Alt  |         Space             |Alt  |blk|Enter|
     `-----------------------------------------------------------'
@@ -117,8 +127,8 @@ Keyboard doesn't send Break code for all keys except for Alt by default.
     |9       0A|o       02|l       29|,       39|          |
     |0       0F|p       03|;       2A|.       3A|          |
     |-       1F|¢      1B|'       2B|/       3B|          |
-    |=       0D|\       1C|{}      2C|???     3C|          |
-    |???     0C|PD2     1D|PD3     2D|RShift  3D|          |
+    |=       0D|\       1C|{}      2C|**2     3C|          |
+    |**1     0C|PD2     1D|PD3     2D|RShift  3D|          |
     |BS      0E|          |          |          |          |
     +----------+---------------------+----------+----------+
     Bit7 is 'press flag' which set 1 on press and 0 on release when break code is enabled.
@@ -139,7 +149,7 @@ Keyboard accepts these commands from host.
     FC  Set Key Flag                            00f6h
     FB  Soft Reset                              0008h
     FA  Reset                                   0000h
-    
+
 
 Keyboard response
 -----------------
@@ -160,7 +170,7 @@ Keyobard sends these bytes to host.
 Set Key Flag command(FC)
 ------------------------
 After 'Power on Reset' firmware enters this command mode and waits for data from host,
-so that you don't need to send 'FC' and it doesn't send any scancode until you send 'FF'.
+so that you don't need to send 'FC' and it doesn't send any scancode until you send 'FF' to exit this mode.
 With Alps models you need to send 'FC' command to enter this mode.
 
 Data sent from host:
@@ -170,8 +180,8 @@ Data sent from host:
          |   `-----`--- scan code
          `------------- enable bit(0: enable repeat, 1: enable break)
 
-    00-7B?  Enable repeat
-    80-FB?  Enable break
+    00-7B   Enable repeat
+    80-FB   Enable break
     FE      Resend(011ah) no need to use
     FF      End(0114h) exits FC command mode.
 
@@ -180,7 +190,1507 @@ Response from keyboard:
     --      OK - No response means that command is accepted.
 
 Examples:
-    To enable break code of all keys.
+    To enable break code of all keys you have to send following commands.
 
     FC 80 81 ... FB FF
 
+
+
+4704 Hardware
+=============
+Power consumption
+-----------------
+This keyboard is very power greedy, it consumes around 170mA
+and USB port may not be able to supply enough current.
+
+    5.061V  -               No load. Power from Powered USB Hub.
+    4.946V  133.6mA max     without Buzzer
+    4.911V  171.0mA max     with Buzzer
+
+
+Controller Board
+----------------
+NOTE: TWO BOLTS OF CONTROLLER BOARD IS CRITICAL.
+Controller PCB and tab of bottom plate of key assembly with two hex bolts, these
+connect between controller ground to the metal bottom plate of key switch assembly.
+This connection is very critical to sense key state, keys will not be registered
+unless they are tightened up with the bolts
+
+    Controller: 8048 DIP40 with 1KB ROM and 64B RAM(8748H?)
+    Clock:      ??MHz   Resonator? TODO: machine cycle: ??us
+    Buffer:     7917 hex buffer
+    Sensor:     IBM custom chip for capacitive sense
+
+
+8048 Pin configuration
+----------------------
+Bus:
+    bit: D7  D6  D5  D4  D3  D2  D1  D0
+    use: BZ  CLK DAT ??? G   S2  S1  S0
+
+    use dir     description
+    ----------------------------------------------------------------------
+    S0  out     Sensor select
+    S1  out     Sensor select
+    S2  out     Sensor select
+    G   out     Sensor strobe?
+    ???         Sensor state out(drive/charge? via 7917 buffer)
+    DAT out     Data via buffer logic with 2K pull up resistor
+    CLK out     Clock via buffer logic with 2K pull up resistor
+    BZ  out     Drive Buzzer via 7917 buffer with 2KOhm pull up resistor(H:on/L:off)
+T0:
+    input of Sensor state(H:on/L:off)
+T1:
+    input of Clock line with 1KOhm pull up resistor
+INT:
+    input of Data line with 1KOhm pull down resistor
+PORT1:
+    P10-P17 matrix row0-7
+PORT2:
+    P20     matrix row8 or I(keyboard identity bits row)
+
+
+Connections
+-----------
+    8048            Sensor
+    -----------------------------
+    D0-2 ====/===== S0-2(Sensor)
+    D3   ---------- STR(Sensor)
+           7917 buffer
+    D4   --|>--+--- OUT(Sensor)
+    T0   ------'
+
+    8048            line
+    -----------------------------
+           Vcc  Vcc
+            |    |
+            R 1K R 2K
+    T1   ---+-<|-+- CLK
+    D6   ---|>---'
+                Vcc
+                 |
+                 R 2K
+    D6   ---|>---+- DAT
+    T1   -+---<|-'
+          R 1K
+          |
+         GND
+                Vcc
+                 |
+                 R 2K
+    D7   ---|>---+- BZ
+
+
+Interruption
+------------
+I       disable at 0015h
+TCNTI   disable at 0014h
+
+
+IBM Capacitive sensor chip
+--------------------------
+Silver canned package
+
+    Pin             Connection      Desciption
+    ----------------------------------------------------------------
+    Input(C0-7)     Matrix Col0-7   8 column line inputs
+    Col select(S0-2)8048:D0-D2      Select column line to sense
+    Strobe(STR)     8048:D3         Strobe
+    Output(OUT)     848:T0          Read Key state(0:pressed/1:released)
+
+    Pinout from bottom:
+    +-----------++------+-------+-------+-------+
+    | 1 2 3 4 5 ||1:LCL |6:LCC  |B:S0   |G:C5   |
+    | 6 7   8 9 ||2:GND |7:LCM  |C:?    |H:C4   |
+    | A       B ||3:Out |8:S2   |D:C6   |I:C3   |
+    | C D   E F ||4:STR |9:S1   |E:C0   |J:C2   |
+    | G H I J K ||5:VCC |A:C7   |F:?    |K:C1   |
+    +-----------++------+-------+-------+-------+
+
+    8048            Sensor
+    D0-2 ====/===== S0-2
+    D3   ---------- STR
+           7917 buffer
+    D4   --|>--+--- OUT
+    T0   ------'
+
+    Speculation: 8048:D4 is used to prepare to sense capacitance.(charge key capcitor?)
+
+Procedure:
+    at 030dh:
+    D0-2=<column>   ; select column S0-2
+    D4=1            ; Prepare sensor(Charge?)
+    P1/P2=<row>     ; select row
+    D0-4=<default>  ; 00010(bus=c2h)
+    D3=1            ; Strobe
+    P1/P2=0         ; unselect row
+    read T0         ; see key state
+
+    at 01afh:
+    D0-2=<column>
+    D4=1
+    D0-2=2(010)     ; select col2
+    P2=01h          ; select row
+    D3=1            ; Strobe
+    P2=00h          ; unselect row
+    read T0
+
+
+Keyswitch Matrix
+----------------
+6019284(62-key):
+     |0       1       2       3       4       5       6       7
+    -|--------------------------------------------------------------
+    0|Enter   RShift  JIS_    PD3     PD2     \|      LofBS   BS
+    1|RAlt    RBlank  /?      '"      {}      Cent!   -       =
+    2|,       .       l       ;       o       p       9       0
+    3|m       n       k       j       u       i       7       8
+    4|Spc     b       g       h       t       y       5       6
+    5|v       c       d       f       e       r       3       4
+    6|LAlt    z       x       s       a       w       q       2
+    7|Reset   LBlank  ISO\    LShift  CapLock PD1     `~      1
+    8|_       x       _       _       x       x       _       _ (Identity bits: 32h)
+
+    Two 15-line flat cables shown from bttom of PCB:
+
+          Flatcable A    Flatcable B
+        /             \/             \
+        0123456789ABCDE0123456789ABCDE
+        --8-----01234567----76543210--
+          Id    row         col         -:GND
+
+
+Keyboard Identity Bits
+----------------------
+4704 keyboards has its identity bit marks on PCB matrix and it is readable
+from firmware so that it can select key layout depending on this.
+
+PCB pictures:
+    Model 100:
+        http://kishy.dyndns.org/wp-content/uploads/2013/02/6019273_0011.jpg
+    Model 200:
+        http://kishy.dyndns.org/wp-content/uploads/2013/02/6019284_0020_capacitive-pcb-top.jpg
+    Model 300:
+        http://kbtalking.cool3c.com/article/23272
+    Model 400:
+        http://kishy.dyndns.org/wp-content/uploads/2011/09/6020218_distrib_0019.jpg
+
+
+
+4704 Firmware
+=============
+
+Startup sequence
+----------------
+Power on Reset(0000h):
+    Short Buzzer
+        turns Buzzer(BZ=L) on at 0002h
+        turns Buzzer(BZ=H) off at 01adh
+    Initialize all memory(3fh-00h)
+    Initialize other registers
+    Read keyboard id and set default parameter at 01afh
+        set break flag for Alt key by default
+    Test and clear memory(3fh..00h) at 0202h
+    Test program memory at 0214h
+    r4=($21&07h)|50h at 0020h
+    Send test result at 022dh
+        sends [a0h | (keyboard id&f0h)>>4] on success
+        6019284 seneds a3h on success
+    Wait for data from host - it expects FC command data followed by ffh(end)
+    Main loop
+
+Soft Reset(0008h):
+    Initialize all memory(20h-00h) It retains parameter memory.
+    Initialize other registers
+    r4=($21&07h)|50h at 0020h
+    Main loop
+
+
+Memory Map
+----------
+RAM(64 bytes):
+$01-07  *Bank0* Registers r0-r7
+        r0  temporary use
+        r1  temporary use
+        r2  temporary use
+        r3  row mask of scan 024dh, 0257h
+        r4  bus default value
+            7 6 5 4 3 2 1 0
+            | | | | | | | |
+            | | | | | `-`-`------ Sensor column select
+            | | | | `------------ Sensor strobe?
+            | | | `-------------- Sensor column set?
+            | | `---------------- Data
+            | `------------------ Clock
+            `-------------------- Buzzer control(L:on/H:off)023ch
+            =$21&07h|50h: call 0020h at 001ch soft reset (52h=0101 0010)
+            =$21&07h|50h: call 0020h at 0109h command FC (52h=0101 0010)
+            =r4|80h: at 00f4h(FD command)
+            =r4&7fh: at 023ch(Main)
+            =r4&f0h: at 0200h
+        r5  repeat dealy/interval
+            used at 02d7h
+            =07h at 02d9h
+            =28h at 02ddh
+            =28h at 02e1h
+       *r6  0bh at 00edh(FD command)
+            used at 0232h
+        r7  received data from host
+            temporary use at 01afh
+            temporary use at 005dh
+            =r4&c0h(current bus value?) 0247h
+$08-17  8-level stack(2*8)
+    $0E
+    :       last key state(1:pressed/0:released)
+    $15     (0E-15)=8*8=64 matrix(for 50-key and 62-key?)
+    $16
+    :       last key state(1:pressed/0:released)
+    $1C     (16-1C)=7*8=56 (extension for 77-key?)
+
+$18-1F  *Bank1* Registers 0-r7
+    Outgoing buffer of data sent to host
+    $1D     r5      outgoing buffer top
+    $1E     r6      outgoing buffer
+    $1F     r7      outgoing buffer bottom
+
+
+$20     Resend buffer: code last sent used by 'Resend'(FE)
+
+$21     Keyboard identity bits
+        0011 0010  (6019284: 32h read from Row(I))
+         ||| ||||
+         ||| |```- Sensor chip control(bus value)??
+         ||| `---- ???
+         ```------ keyboard model id
+
+        set at 01fah on Power on Reset:  32h from row8(I)(6019284)
+        got at 0020h on Soft Reset:
+        got at 034eh on translate into scan code:
+        got at 0125h on command FC:
+        set from scan 8(I) row at 01fdh
+
+        Keyboard model id:
+            Model 100 6019273 50-key (grid layout):     22h(from picture)
+            Model 200 6019284 62-key Alpha(60% layout): 32h
+            Model 300 6019303 77-key Expanded Alpha:    42h?(from dump list)
+            Model 400 6020218 107-key Full key:         no identity
+                Looks like this firmware does not support 107-key.
+
+        IBM 4704 keyboards:
+            It seems Model 100, 200 and 300 keyboards share one firmware code and
+            have small square copper patterns on righ side of PCB to identify
+            its layout. See following pictures. Model 400 may use another firmware.
+
+$22-3F  30-byte Parameter RAM(Repeat and Break flags)
+        Parameter byte is comprised of four flag pairs. Flags occupies two bits each a key.
+        Parameter RAM can have flags for 120(4*30) keys.
+
+        Parameter byte and flags:
+            bit 7   6   5   4   3   2   1   0
+                3r  3b  2r  2b  1r  1b  0r  0b
+:
+$3F     End of Memory(64 bytes)
+
+
+
+
+Entry points
+------------
+0020    Soft Reset  r4=($21&07h)|50h = (32h&07h)|50h=52h
+0029    r1=r1+(a), a=r0 (page 0)
+002c    (F0=0: send or receive data with 'interpret command mode')
+002d    Receive data or Send scan code
+0035    Send scan code
+        return: F1=1
+0082    Receive data from host
+        condition: F0==0   interpret command
+                   F0==1   return receive data(a)
+        return:    F1=1(ERROR) 00c7 (Receive ACK/Parity Error) 00b6,00ce
+                   F1=0?
+                   a=recieve data, (with F0=0 00dc) F0==0 means 'data received'
+00bc    push 7f(error) into outgoing buffer
+00be    push data/response into outgoing buffer(r5,r6,r7)
+00d2    interpret keyboard command
+00de    calculate parity
+
+01a4    r1=r1+(a), a=r0 (page 1)
+01a5    r1=r1+a, a=r0
+01a9    Buzzer and Scan row8(*) and set param: call from Power on Reset 0018h
+01af    Read keyboard identity bits from row8(I) and set param: - call from command FC 0107h
+0202    Memory Test(Power on Reset)
+
+0230    Main loop:  send, receive data and scan
+        send/receive: call 002c
+0263    **Scan matrix**(F1==0): F1=1, r1=15h, r2=3fh, r3=01h
+0287    **Scan matrix**(F1==1): F1=0, r1=1ch, r2=77h, r3=02h
+0325    get key configure flags(a=-----rb; where r:repeat enable, b:break enable)
+0339    queue data at bottom of outgoing buffer
+034e    translate into scan code
+        scan code table1/table2
+
+
+Keyboard command entry points
+-----------------------------
+FF: jump_table0   Soft Reset(008h)
+FE: jump_table1   Resend(return content of $20)
+FD: jump_table2   Short beep BZ
+FC: jump_table3   parameter configuration(100h)
+FB: jump_table4   Soft Reset(008h)
+FA: jump_table5   Reset(000h)
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+;  8048 Disassembly of IBM 6019284 ROM dump
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; label mnemonic                ; address   comment
+;-------------------------------------------------------------------------------------
+       org     000h
+; jump_table:5  Hard Reset/Power on Reset
+       mov     a,#07fh         ; 0000 - a=7f        Power on Reset
+       outl    bus,a           ; 0002 - BZ=L(off), others=H
+       mov     r0,#03fh        ; 0003 - r0=3fh
+       clr     f1              ; 0005 - F1=0
+       jmp     X000c           ; 0006 -
+; jump_table:0,4 Soft Reset
+       mov     r0,#020h        ; 0008 - r0=20h      $20=resend buffer
+       clr     f1              ; 000a -
+       cpl     f1              ; 000b - F1=1
+
+;;;;;;;;;;;;;;;;;;
+;   initialize memory
+;       hard reset  clear 3f-00h    F1=0
+;       soft reset  clear 20-00h    F1=1
+X000c: clr     f0              ; 000c - F0=0
+       clr     a               ; 000d - a=0
+X000e: mov     @r0,a           ; 000e - @r0=0   r0=$3f(hard)/$20(soft)
+       djnz    r0,X000e        ; 000f - clear RAM 3f/20h to $00
+       mov     psw,a           ; 0011 - psw=0
+       outl    p1,a            ; 0012 - p1=0
+       outl    p2,a            ; 0013 - p2=0
+       dis     tcnti           ; 0014 - disable timer overflow
+       dis     i               ; 0015 - disable INT
+       jf1     X001c           ; 0016 - jump if F1==1(Soft Reset?)
+
+; F1==0 Power on Reset
+       call    X01a9           ; 0018 - read keyboard id and set default parameter
+       jmp     X0202           ; 001a - Memory Test and go to Main
+
+; F1==1 Soft Reset
+X001c: call    X0020           ; 001c - ; r4=$21&07h|50h(52h?), a=r4
+       jmp     X0230           ; 001e - ; go to Main
+
+;;;;;;;;;;;;;;;;;;
+; Set r4
+: INPUT:    r4???
+: RETURN:   a=r4(original)
+;           r4=$21&07h|50h
+;
+X0020: mov     r0,#021h        ; 0020 -  r0=21h(keyboad identity bits)
+       mov     a,@r0           ; 0022 -  a=($21)
+       anl     a,#007h         ; 0023 -  a=a&07h
+       orl     a,#050h         ; 0025 -  a=a|50h
+       xch     a,r4            ; 0027 -  swap a,r4
+       ret                     ; 0028 -
+
+; read program memory @page0
+; INPUT: a:address
+; OUTPUT: a=(a)@page0
+X0029: movp    a,@a            ; 0029 -
+       jmp     X01a5           ; 002a - r1=r1+a, a=r0
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Receive data or Send scan code
+; INPUT:    F0=0:interpret command/1:retern data            used in Receive command/data
+; OUTPUT:   F0=0(received)/1(not received)
+; DONE: a=0, F1=1, buffer rotate
+X002c: clr     f0              ; 002c - F0=0
+X002d: jnt1    X0082           ; 002d - go to receive if T1(CLK)==L
+       sel     rb1             ; 002f - switch to bank1
+       mov     a,r5            ; 0030 - a=r5(bank1)            r5(bank1): scan code buffer
+       sel     rb0             ; 0031 - switch to bank0
+       jnz     X0035           ; 0032 - jump if r5(bank1)!=0
+       retr                    ; 0034 - return if r5(bank1)==0 buffer empty
+
+;;;;;;;;;;;;;;;;;;
+; Send scan code
+; INPUT:    a=data
+; OUTPUT:   F1=1:Sent,Rotate,Data ready/0:???
+X0035: dec     a               ; 0035 - a--
+       clr     c               ; 0036 - c=0
+       call    X00de           ; 0037 - c=parity calc
+       jnt1    X0082           ; 0039 - go to receive if T1(CLK)=L
+; Start bit
+       anl     bus,#0bfh       ; 003b - [CLK=L]
+       orl     bus,#020h       ; 003d - [DATA=H]        [[[Start bit]]]
+       mov     r0,#010h        ; 003f - r0=10h
+
+
+; check inhibited(DATA==L) - check DATA line released by host
+X0041: jni     X0047           ; 0041 - jump if DATA==L LOOP>
+       jni     X0049           ; 0043 - jump if DATA==L
+       jmp     X0054           ; 0045 - cont. if DATA==H
+X0047: jmp     X0049           ; 0047 -
+X0049: djnz    r0,X0041        ; 0049 - <LOOP  timeout?
+; time out - end
+       orl     bus,#040h       ; 004b - [CLK=H]
+       anl     bus,#0dfh       ; 004d - [DATA=L]       [[[idle state]]]
+       retr                    ; 004f - return send end(give up with inhibited)
+
+
+; check data==7eh   Keep data in 'Resend' buffer unless it is 7eh
+X0050: xrl     a,#07eh         ; 0050 - revert a
+       jmp     X005d           ; 0052 -
+
+X0054: mov     r0,#020h        ; 0054 - r0=20h 'Resend' Buffer
+       xrl     a,#07eh         ; 0056 - a=a^7eh(0111 1110)
+       jz      X0050           ; 0058 - jump if a==7eh
+; a!=7eh        retain data to $20(resend buffer) if data is not 7eh
+       xrl     a,#07eh         ; 005a - revert a
+       mov     @r0,a           ; 005c - $20=a  retain a to 'Resend' buffer
+
+
+; Data bit0-7 and Parity(c)
+; Pulse H:18/L:9??
+X005d: mov     r7,#009h        ; 005d - r7=9
+X005f: mov     r0,#009h        ; 005f - r0=9 LOOP>>
+       jb0     X0069           ; 0061 - jump if a:bit0==1
+; a:bit0==0
+; send DATA=0
+       anl     bus,#0dfh       ; 0063 - [DATA=L]
+       orl     bus,#040h       ; 0065 - [CLK=H]
+       jmp     X006f           ; 0067 -
+; a:bit0==1
+; send DATA=1
+X0069: orl     bus,#020h       ; 0069 - [DATA=H]
+       orl     bus,#040h       ; 006b - [CLK=H]
+       jmp     X006f           ; 006d -
+; hold CLK=H
+X006f: djnz    r0,X006f        ; 006f - 9*2cycle delay (around 60us??)
+       anl     bus,#0bfh       ; 0071 - [CLK=L]
+       rrc     a               ; 0073 - a=a>>1, c=a:bit0
+       djnz    r7,X005f        ; 0074 - <<LOOP
+; Stop bit
+; a=0, F1=1, buffer rotate
+       anl     bus,#0dfh       ; 0076 - [DATA=L]           [Idle]  End
+       clr     a               ; 0078 - a=0
+       clr     f1              ; 0079 -
+       cpl     f1              ; 007a - F1=1               [Sent?]
+       orl     bus,#040h       ; 007b - [CLK=H]            [Idle]  End
+; remove from outgoing buffer: r7=0, r6=r7, r5=r6
+       sel     rb1             ; 007d - switch to bank1
+       xch     a,r7            ; 007e -
+       xch     a,r6            ; 007f -
+       xch     a,r5            ; 0080 - 0->r7->r6->r5->a  [Bank1 Buffer rotate]
+       retr                    ; 0081 - retr reverts to bank0
+
+
+
+;;;;;;;;;;;;;;;;;;
+; Receive command/data from host
+; INPUT:    F0=0:interpret command/1:return data(used by command)
+; OUTPUT:   F0=0(received)/1(not received)
+;           F1=1:Error/0:OK
+; a: data
+; c: parity
+; F1: 0: Receive or Send 1: Receive
+;
+X0082: jf1     X0086           ; 0082 -  jump if F1==1
+; F1==0
+       jmp     X002d           ; 0084 -  Can't recevie, do 'Receive or Send' again
+; F1==1
+X0086: mov     r0,#006h        ; 0086 -  r0=6h
+X0088: djnz    r0,X0088        ; 0088 -  6*2cycle dealy
+       jt1     X00cb           ; 008a -  return if T1(CLK)==H
+       anl     bus,#0bfh       ; 008c -  [CLK=L]
+       orl     bus,#020h       ; 008e -  [DATA=H]                  [Start bit]
+       mov     r0,#011h        ; 0090 -
+X0092: djnz    r0,X0092        ; 0092 -  11*2cycle delay
+       mov     r7,#009h        ; 0094 -  r7=9h
+X0096: orl     bus,#040h       ; 0096 -  LOOP>[CLK=H]              [Clock up for receive]
+       mov     r0,#008h        ; 0098 -
+X009a: djnz    r0,X009a        ; 009a -  8*2cycle delay
+       anl     bus,#0bfh       ; 009c -  [CLK=L]                   [Clock down]
+       jni     X00a9           ; 009e -  jump if INT(DATA)==L      [Read bit] Read twice for debounce?
+; DATA==H
+       orl     a,#001h         ; 00a0 -  a:bit0=1
+       jni     X00ad           ; 00a2 -  jump if INT(DATA)==L
+; DATA==H
+X00a4: rrc     a               ; 00a4 -  a=a>>1 with carry         [Next bit]
+       djnz    r7,X0096        ; 00a5 -  <LOOP
+       jmp     X00b0           ; 00a7 -                            [go to Stop]
+; DATA==L
+X00a9: anl     a,#0feh         ; 00a9 - a:bit0=0
+       jni     X00a4           ; 00ab -  jump if INT(DATA)==L
+; DATA==H
+X00ad: clr     f1              ; 00ad -  F1=0                      [Receive Error]
+       jmp     X00a4           ; 00ae -
+
+
+; wait for Stop/ACK (DATA=H)
+; F0: 0=jump table, 1=return(with F0=0)
+X00b0: orl     bus,#040h       ; 00b0 - [CLK=H]                    [Idle] End
+       mov     r0,#004h        ; 00b2 -
+X00b4: djnz    r0,X00b4        ; 00b4 - 4*2cycle? 8*0.2us=1.6us?
+       jni     X00c7           ; 00b6 - jump if INT(DATA)==L       [Stop Error] *no error response?
+; DATA==H
+       anl     bus,#0dfh       ; 00b8 - [DATA=L]                   [Idle] End
+       jf1     X00cc           ; 00ba - jump if F1==1
+; F1==0                                                             [Receive Error]
+
+
+; push 7eh into outgoing buffer (Receive Error at 00bah/Parity Error at 00ceh)
+X00bc: mov     a,#07eh         ; 00bc - 7eh: error response
+
+; push data into top of outgoing buffer(Error response)
+; a:data
+; r5=a, r6=r5, r7=r6
+X00be: sel     rb1             ; 00be - switch to bank1
+       inc     a               ; 00bf - a++
+       xch     a,r5            ; 00c0 - a->r5->r6->r7->a
+       xch     a,r6            ; 00c1 -
+       xch     a,r7            ; 00c2 -
+       jz      X00cb           ; 00c3 - jump if a==0
+       mov     r7,#0ffh        ; 00c5 - r7=ffh overflow            [Over flow:FE]
+
+X00c7: anl     bus,#0dfh       ; 00c7 - [DATA=L]                   [Idle] End
+       clr     f1              ; 00c9 -
+       cpl     f1              ; 00ca - F1=1                       [Error flag]
+X00cb: retr                    ; 00cb -
+
+
+
+; check parity of recieve data
+; F1==1
+X00cc: call    X00de           ; 00cc - call parity calc
+       jc      X00bc           ; 00ce - jump if carryflag=1    (Parity ERROR)
+; parity OK
+       jf0     X00dc           ; 00d0 - jump if F0==1
+
+
+;;;;;;;;;;;;;;;;;
+; F0==0
+; Interpret command
+;
+       cpl     a               ; 00d2 - compliment a       ffh-a(command)
+       add     a,#jump_table   ; 00d3 - a=a+#jump_table
+       jc      X00d8           ; 00d5 -
+       jmpp    @a              ; 00d7 - jump table             [Keyboard command]
+; Command Out bound Error
+X00d8: mov     a,#0fdh         ; 00d8 -    error response: FD
+       jmp     X00be           ; 00da -
+
+;;;;;;;;;;;;;;;;;
+; F0==1
+; Return data
+X00dc: cpl     f0              ; 00dc - F0=~F0(=0)
+       ret                     ; 00dd -
+;
+; recieve data/command
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+;;;;;;;;;;;;;;;;;;
+; calculate parity: 'c' depends on number of '1' in 'a'
+;   INPUT: a=data
+;   OUTPUT: c(carry flag)
+X00de: mov     r0,#008h        ; 00de - b8 08  8.  r0=8h
+X00e0: rr      a               ; 00e0 - 77     w   a=a>>1
+       jb0     X00e4           ; 00e1 - 12 e4  .d  jump if a:bit0==1
+       cpl     c               ; 00e3 - a7     '   compliment carry flag
+X00e4: djnz    r0,X00e0        ; 00e4 - e8 e0  h`  jump if --r0!=0
+       cpl     c               ; 00e6 - a7     '
+       ret                     ; 00e7 - 83     .
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Keyboard command  jump table
+;
+; jump_table:1 FE   Resend(return content of $20)
+X00e8: mov     r0,#020h        ; 00e8 -  $20
+       mov     a,@r0           ; 00ea -  a=$20 get from resend buffer
+       jmp     X00be           ; 00eb -  push into outogoing buffer
+
+; jump_table:2 FD   r6=0bh, r4=r4|80h
+       mov     r6,#00bh        ; 00ed -  r6=0bh  BZ duration(scan cycles)?
+       orl     bus,#080h       ; 00ef -  BZ=H(on)
+       mov     a,r4            ; 00f1 -
+       orl     a,#080h         ; 00f2 -  BZ=H
+       mov     r4,a            ; 00f4 -  r4=r4|80h BZ=H(on) bus-default
+       retr                    ; 00f5 -
+
+; jump_table:3 FC
+       mov     r1,#01eh        ; 00f6 -  r1=1eh
+       jmp     X0100           ; 00f8 -
+
+;
+; keyboard commands:
+;
+; FF: jump_table0   Soft Reset(008h)
+; FE: jump_table1   Resend(return content of $20)
+; FD: jump_table2   BZ set BZ=H(on) to bus and r4(bus-default), duration to r6
+; FC: jump_table3   Set key configuration
+; FB: jump_table4   Soft Reset(008h)
+; FA: jump_table5   Reset(000h)
+;
+jump_table:    db      008h,0e8h,0edh,0f6h,008h,000h           ; 00fa .hmv..
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; command FC    parameter configuration
+;   clear $22-3f, then set data received from host
+;
+; r4:
+;   set to $21&07h|50h
+; r7: received data
+;   r7=data|7fh
+;       F0=0 if data:bit7=1
+;       F0=1 if data:bit7=0
+;
+; data received(r7):
+;   FF      End(0114h)
+;   FE      Resend and receive again(011ah)
+;   FF-80   F0=0    if bit7 of r7 is set
+;   7F-00   F0=1    if bit7 of r7 is reset
+;
+;
+
+;;;;;;;;;;;;;;;;;;
+; clear parameter configuration RAM $3f..22
+; INPUT: r1=1eh=30
+;   called at 00f6h
+X0100: clr     a               ; 0100 - a=0
+       mov     r0,#03fh        ; 0101 - r0=3f
+X0103: mov     @r0,a           ; 0103 - $3f=a
+       dec     r0              ; 0104 - r0--
+       djnz    r1,X0103        ; 0105 -
+       call    X01af           ; 0107 - Read keyboar id and set parameter flags
+       call    X0020           ; 0109 - r4=($21 & 07h | 50h) =52h
+
+;;;;;;;;;;;;;;;;;;
+; data receive from host
+;
+X010b: clr     f0              ; 010b - LOOP>>
+       cpl     f0              ; 010c - F0=1
+X010d: call    X002d           ; 010d - receive/send data with F0=1
+       jf0     X010d           ; 010f - LOOP while F0==1
+
+
+; received data from host(F0==0)
+       mov     r7,a            ; 0111 - r7=data received
+       cpl     c               ; 0112 - c=~c
+       cpl     a               ; 0113 - a=~a
+
+;;;;;;;;;;;;;;;;;
+; a==FF *End*
+       jz      X013b           ; 0114 - return if a==FF
+       xrl     a,#001h         ; 0116 -
+       jnz     X011e           ; 0118 - jump if a!=FE
+
+;;;;;;;;;;;;;;;;;
+; a==FE *Resend*
+       call    X00e8           ; 011a - Resend         and continue...
+       jmp     X010b           ; 011c - <<LOOP         Send/Receive loop again
+
+;;;;;;;;;;;;;;;;;
+; else  *Set flag*
+;   data:bit7=1:enable break/0:enable repeat
+X011e: mov     a,r7            ; 011e - a=r7(data received)
+       jb7     X0122           ; 011f - jump if a:bit7==1  (1xxx xxxx)
+       cpl     f0              ; 0121 - F0=~F0=1   if a:bit7==0    [F0=1 means data:bit7==0]
+X0122: anl     a,#07fh         ; 0122 - a=a&7fh                    [data:bit6-0=scan code]
+       mov     r7,a            ; 0124 - r7=a
+
+
+; identify keybaord from $21=keyboar identity bits
+       mov     r1,#021h        ; 0125 - r1=21h
+       mov     a,@r1           ; 0127 - a=($21)
+       anl     a,#0f0h         ; 0128 - a=a&f0h
+       xrl     a,#020h         ; 012a - a=a^20h
+       jz      X013c           ; 012c - jump if $21==0010 xxxx     6019273 50-key?
+       xrl     a,#010h         ; 012e - a=a^10h
+       jz      X0142           ; 0130 - jump if $21==0011 xxxx     *6019284 62-key*
+       xrl     a,#070h         ; 0132 - a=a^70h
+       jz      X0148           ; 0134 - jump if $21==0100 xxxx     6019303 77-key?
+
+; Unknown keyboard
+       mov     a,r7            ; 0136 - a=r7(received data)
+       call    X015f           ; 0137 -                                [Set flag]
+       jmp     X010b           ; 0139 - <<LOOP receive again
+
+; End
+X013b: retr                    ; 013b -
+
+
+
+; Set 'index' and 'size' scan code table for each keyboard model
+;   r1: end of scan code table(index)
+;   r2: number of scan code table(size)
+; 6019273 50-key?
+X013c: mov     r1,#0afh        ; 013c - r1=afh     address@page3   03afh(table1)
+       mov     r2,#038h        ; 013e - r2=38h     0011 10(00)     56keys
+       jmp     X014c           ; 0140 -
+
+; *6019284 62-key*
+X0142: mov     r1,#0efh        ; 0142 - r1=efh     address@page3   03efh(table2)
+       mov     r2,#040h        ; 0144 - r2=40h     0100 00(00)     64keys
+       jmp     X014c           ; 0146 -
+
+; 6019303 77-key?
+X0148: mov     r1,#0ffh        ; 0148 - r1=ffh     address@page3   03ffh(table2)
+       mov     r2,#050h        ; 014a - r2=50h     0101 00(00)     80keys
+
+
+
+; get scancode from table and test loop
+LOOP>>
+X014c: mov     a,r1            ; 014c - a=r1
+       movp3   a,@a            ; 014d - a=(r1)     read scan code table
+       xrl     a,r7            ; 014e - a=a^r7     a==r7(received scan code)
+       jnz     X0156           ; 014f -
+
+; scan code(a) == received data(r7)
+       dec     r2              ; 0151 - r2--
+       mov     a,r2            ; 0152 - a=r2
+       call    X015f           ; 0153 - call                           [Set flag]
+       inc     r2              ; 0155 - r2++
+
+; check next scan code
+X0156: dec     r1              ; 0156 - r1--               r1: address of table
+       djnz    r2,X014c        ; 0157 - <<LOOP while --r2  r2: number of table
+
+       jnc     X015d           ; 0159 - jump if r1>=0
+       call    X00d8           ; 015b - Error: FD and cont.            [Out of bound Error: FD]
+X015d: jmp     X010b           ; 015d - <<LOOP Receive next data
+;;;
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Set flag routine
+;
+; INPUT: a=table index(number of table)
+;        a: AAAA AAFF(AAAAAA:index of parameter RAM, FF: flag position(0-3))
+;
+X015f: clr     c               ; 015f - c=0
+                                ; calculate RAM address
+       mov     r2,a            ; 0160 - r2=a       r2=data
+       rr      a               ; 0161 - a=a>>1
+       rr      a               ; 0162 - a=a>>1     a/4(four keys per a parameter byte)
+       add     a,#022h         ; 0163 - a=a+22h    start of parameter bytes
+       mov     r0,a            ; 0165 - r0=a       r0=parameter address
+
+       mov     a,r2            ; 0166 - a=r2
+       anl     a,#003h         ; 0167 - a=a&03h            [a=flag position]
+       jz      X017e           ; 0169 - if FF==0b00
+       dec     a               ; 016b - a--
+       jz      X018a           ; 016c - if FF==0b01
+       dec     a               ; 016e - a--
+       jz      X0197           ; 016f - if FF==0b10
+
+;
+; Parameter byte and configure flags
+;   bit 7   6   5   4   3   2   1   0
+;       3r  3b  2r  2b  1r  1b  0r  0b
+
+;;;;;;;;;;;;;;;;;;
+; FF==11b:  3r/3b
+       mov     a,@r0           ; 0171 - a=(r0)             r0=parameter address
+       anl     a,#03fh         ; 0172 - a=a&0011 1111b     clear 3r/3b
+       jf0     X017a           ; 0174 - jump if F0==1
+; F0==0(received data:bit7==1)
+; a=a|40h
+       orl     a,#040h         ; 0176 - a=a|0100 0000b     3b: break enabled
+
+
+
+;;;;;;;;;;;;;;;;;;
+; store to RAM and return
+X0178: mov     @r0,a           ; 0178 - (r0)=a store parameter to RAM
+       ret                     ; 0179 - return a: command/received data
+; End of Set flag
+;;;;;;;;;;;;;;;;;;
+
+
+
+; F0==1 (data:bit7==0)
+; a=a|80h
+X017a: orl     a,#080h         ; 017a - a=a|1000 0000b     3r: repeat enabled
+       jmp     X0178           ; 017c -
+;;;
+
+
+;;;;;;;;;;;;;;;;;;
+; FF==00b:  0r/0b
+X017e: mov     a,@r0           ; 017e - a=(r0)
+       anl     a,#0fch         ; 017f - a=a & 1111 1100b   clear 0r/0b
+       jf0     X0186           ; 0181 - jump if F0==1
+; F0==0(data:bit==1)
+       inc     a               ; 0183 - a++                0b: break enabled
+       jmp     X0178           ; 0184 -
+; F0==1(data:bit==0)
+X0186: orl     a,#002h         ; 0186 -                    0r: repeat enabled
+       jmp     X0178           ; 0188 -
+;;;
+
+
+;;;;;;;;;;;;;;;;;;
+; FF==01b:  1r/1b
+X018a: mov     a,@r0           ; 018a -
+       anl     a,#0f3h         ; 018b -                    clear 1r/1b
+       jf0     X0193           ; 018d -
+; F0==0(data:bit==1)
+       orl     a,#004h         ; 018f -                    1b: break enabled
+       jmp     X0178           ; 0191 -
+; F0==1(data:bit==0)
+X0193: orl     a,#008h         ; 0193 -                    1r: repeat enabled
+       jmp     X0178           ; 0195 -
+;;;
+
+
+;;;;;;;;
+; FF==10b   parameter|10h / parameter|20h
+X0197: mov     a,@r0           ; 0197 -
+       anl     a,#0cfh         ; 0198 -                    clear 2r/2b
+       jf0     X01a0           ; 019a -
+; F0==0(data:bit==1)
+       orl     a,#010h         ; 019c -                    2b: break enabled
+       jmp     X0178           ; 019e -
+; F0==1(data:bit==0)
+X01a0: orl     a,#020h         ; 01a0 -                    2r: repeat enabled
+       jmp     X0178           ; 01a2 -
+;;;
+
+
+;
+; End of command FC
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+
+;;;;;;;;;;;;;;;;;;
+; read program memory @page1
+;   INPUT: a=address of program memory
+X01a4: movp    a,@a            ; 01a4 - a=(a)@page1
+
+;   OUTPUT: r1=r1+a, a=r0
+; r1=r1+a,a=r0
+X01a5: add     a,r1            ; 01a5 -
+       mov     r1,a            ; 01a6 - r1=a+r1
+       mov     a,r0            ; 01a7 - a=r0
+       ret                     ; 01a8 -
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Scan row8(I) and set parameter flags(on Power on Reset)
+;
+; call from hard reset 0018h with a=0, r0=0, r1=0?
+;   INPUT: r0, r1: for wait loop
+;   OUTPUT: $21=keybaord identity bits, r4=$21&f0h
+;
+
+;;;;;;;;;;;;;;;;;;
+; delay to make Buzzer audible when powering up??
+X01a9: djnz    r0,X01a9        ; 01a9 - r0*2cycle
+       djnz    r1,X01a9        ; 01ab - r1*(r0*2cycle+2cycle) 256*(256*2+2)=131584(2us?/cycle) around 260ms??
+       anl     bus,#0c0h       ; 01ad - BZ=_,CLK=_,DATA=L  line is idle
+
+
+;;;;;;;;;;;;;;;;;;
+;
+; Read keyboard identity bits from row8(I) and set parameter flags(on command FC)
+;   INPUT: a=0
+;   OUTPUT: r4=a=scanned data of row8(I)=keyboard identity bits
+;
+;   F0: 1:read(frist)/0:read(second)&settle
+;        It needs to read same value twice to settle.
+;
+;   Keyboar id bit pattern on PCB:
+;       mark:       1
+;       brank:      0
+;   Sensor value meaning:
+;       Sensor:     0           1
+;       Kbd id:     1(mark)     0(blank)
+;       Key:        1(pressed)  0(released)
+;
+; called from command FC 0107h
+X01af: mov     r7,#008h        ; 01af - r7=08h                 [column]
+X01b1: rl      a               ; 01b1 - a=a<<1 LOOP_0{         [next column]
+X01b2: mov     r4,a            ; 01b2 - LOOP{  r4=a            [data]
+       cpl     f0              ; 01b3 - F0=~F0     toggle F0   [read twice to debounce]
+       mov     a,r7            ; 01b4 - a=r7
+       dec     a               ; 01b5 - a--
+       orl     a,#0c0h         ; 01b6 - col(7-0)|c0h = c7-c0h  BZ=H:on [Beep during FC command]
+       outl    bus,a           ; 01b8 -                        [Select column]
+       orl     bus,#010h       ; 01b9 - D4=1                   [charge sensor out=H?]
+       mov     a,#0d2h         ; 01bb - 1101 0010
+       outl    bus,a           ; 01bd - bus=d2h   D4-0=10010   select column 2?
+
+;
+       orl     p2,#001h        ; 01be - P2:0=1                 [select row8(I)]
+       mov     a,r4            ; 01c0 - a=r4(data)
+       orl     bus,#008h       ; 01c1 - bus=d2h|08h=dah  D4=1  [Strobe?](1101 1010)
+       anl     p2,#000h        ; 01c3 - P2:0=L                 [unselect row8(I)]
+
+; check sensor out(T0)
+       jt0     X01d5           ; 01c5 - jump if T0==H
+       jf0     X01cd           ; 01c7 - jump if F0==1
+       jb0     X01d9           ; 01c9 - jump if a:bit0==1      [Settle]
+        ; TO(sensor)==0 && F0==0 && a:bit0==0
+       jmp     X01b2           ; 01cb -  }LOOP
+
+; record 1(a=a|01h) when key is on(T0=L) and F0==1
+; T0(sensor)==L(off) && F0==1 (from 01c7)
+X01cd: orl     a,#001h         ; 01cd - a=a|1                  [Set a:bit0=H]
+       jmp     X01b2           ; 01cf - LOOP
+
+; record 0(a=a&feh) when key is off(T0=H) and F0==0
+; T0(sensor)==H(on) && F0==0 && a:bit0==1(off) (from 01d7)
+X01d1: anl     a,#0feh         ; 01d1 - a=a&feh                [Set a:bit0=L]
+       jmp     X01b2           ; 01d3 - LOOP
+
+; scan LOOP again
+; T0(sensor)==H(on) && F0==1 (from 01c5)
+X01d5: jf0     X01b2           ; 01d5 - LOOP while F0==1
+
+; T0(sensor)==H(on) && F0==0
+       jb0     X01d1           ; 01d7 - jump if a:bit0==1 [need to change r4(a) to 0]
+
+; next column
+; T0(sensor)==H && F0==0 && a:bit0==0 OR
+; T0(sensor)==L && F0==0 && a:bit0==1   (from 01c9)
+X01d9: djnz    r7,X01b1        ; 01d9 - }LOOP_0 while --r7>0 [Next column]
+       mov     r4,a            ; 01db - r4=a               a=r4=scanned data of Row8(I)
+
+
+;;;;;;;;;;;;;;;;;;
+;  Set parameters from scanned data of row 8(I)
+;
+;   INPUT:  a=r4=keyboard identity bits
+;   OUTPUT: $21=keybaord identity bits, r4=$21&f0h
+;
+       anl     a,#0f0h         ; 01dc - a=a&f0h
+       xrl     a,#020h         ; 01de - a=a^20h            (a==0010 xxxx)  6019273
+       jz      X01ec           ; 01e0 - jump if a==0
+       xrl     a,#010h         ; 01e2 - a=a^10h            (a==0011 xxxx) *6019284 when power on reset
+       jz      X01f2           ; 01e4 - jump if a==0
+       xrl     a,#070h         ; 01e6 - a=a^70h            (a==0100 xxxx)  6019303
+       jz      X01f2           ; 01e8 - jump if a==0
+       jmp     X01fa           ; 01ea -
+
+; $21==(0010 xxxx)  for 6019273(50-key)
+; set break enalbe flag for Reset(or on other layout?)
+X01ec: mov     r0,#022h        ; 01ec -
+       mov     @r0,#001h       ; 01ee - $22=1      $22:bit0=break enable falg of ????
+       jmp     X01fa           ; 01f0 -
+
+; $21==(0011 0010 | 0100 xxxx)  for 6019284(62-key) or 6019303(77-key) layout
+; set break enable flag for LAlt and RAlt *6019284
+X01f2: mov     r0,#02eh        ; 01f2 -
+       mov     @r0,#001h       ; 01f4 - $2e=1      $2e:bit0=break enable flag of LAlt
+       mov     r0,#024h        ; 01f6 -
+       mov     @r0,#001h       ; 01f8 - $24=1      $24:bit0=break enable flag of RAlt
+
+; set $21 to scanned data of row 8(I)   [keyboard identity bits]
+X01fa: mov     r0,#021h        ; 01fa -
+       mov     a,r4            ; 01fc -
+       mov     @r0,a           ; 01fd - ($21)=r4     $21: r4=identity bits(row 8(I))
+       anl     a,#0f0h         ; 01fe -
+       mov     r4,a            ; 0200 - r4=r4&f0h
+       ret                     ; 0201 -
+;
+; End of Scan row8(I)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Test and clear memory(3fh..00h) on Power on Reset
+;
+X0202: mov     r0,#03fh        ; 0202 -  $3f
+X0204: mov     a,@r0           ; 0204 -  LOOP>>
+       mov     r1,a            ; 0205 -  r1=(r0) r0=3f..00
+       mov     a,#0ffh         ; 0206 -  a=ffh
+       mov     @r0,a           ; 0208 -  (r0)=ffh
+       xrl     a,@r0           ; 0209 -  a=a^ffh =0??
+       jnz     X0224           ; 020a -  jump if a!=ffh    *always should be a=zero*
+       mov     @r0,a           ; 020c -  (r0)=a    (=0)
+       mov     a,@r0           ; 020d -  a=(r0)
+       jnz     X0224           ; 020e -  jump if a!=ffh    *always should be a=zero*
+       mov     a,r1            ; 0210 -  a=r1
+       mov     @r0,a           ; 0211 -  (r0)=a (revert to origin value)
+       djnz    r0,X0204        ; 0212 -  <<LOOP --r0
+
+;
+; Test program memory(0,255..1 @page0,1,2,3)
+;
+; INPUT: r0=0 r4=??
+; OUTPUT: r4=$21&07h|50h, a=swapHL(r4(original)) or feh
+X0214: mov     a,r0            ; 0214 -  LOOP>>   a=r0=0
+       call    X0029           ; 0215 -  r1=r1+(a), a=r0 (page0)
+       call    X01a4           ; 0217 -  r1=r1+(a), a=r0 (page1)
+       movp    a,@a            ; 0219 -
+       call    X01a5           ; 021a -  r1=r1+(a), a=r0 (page2)
+       movp3   a,@a            ; 021c -
+       call    X01a5           ; 021d -  r1=r1+(a), a=r0 (page3)
+       djnz    r0,X0214        ; 021f -  <<LOOP --r0
+       mov     a,r1            ; 0221 -  a=r1  sum of program memory data
+       jz      X0226           ; 0222 -  sum of program memory data != 0 if no error ???
+
+; Send FE on error and r4 on success
+X0224: mov     r4,#0efh        ; 0224 -  r4=efh    Memory error
+X0226: call    X0020           ; 0226 -  r4=$21&07h|50h, a=r4(keyboard id or efh)
+       swap    a               ; 0228 -  swap a:h<->a:l
+       orl     a,#0a0h         ; 0229 -  a=a|a0h(1010 iiii)    i:keyboard id(hi-bits)
+       call    X0339           ; 022b -  queue data(a) to buffer
+       call    X010b           ; 022d -  send kbd ID and wait for data from host   [FC command]
+       strt    t               ; 022f -  start timer
+; Usually first data form keyboard at startup is A3h(sum of program memory?).
+; FEh for memory error??
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Main??
+;
+; check scan code buffer to send
+X0230: call    X002c           ; 0230 - receive/send data
+       mov     a,r6            ; 0232 - a=r6 set by command FD Short Beep(0bh at 00edh)
+       jz      X023d           ; 0233 -
+       djnz    r6,X023d        ; 0235 - r6--
+; Buzzer off
+       anl     bus,#07fh       ; 0237 - BZ=L(off)   when get to r6==0  [Short Beep ends]
+       mov     a,r4            ; 0239 -
+       anl     a,#07fh         ; 023a -
+       mov     r4,a            ; 023c - r4=r4&7fh(BZ=L:off) r4=bus-default
+
+; delay for scan    192*32cycle?
+X023d: mov     a,t             ; 023d - a=t(timer)
+       add     a,#064h         ; 023e - a=a+64h
+       jnc     X023d           ; 0240 - delay for scan
+       clr     a               ; 0242 - a=0
+       mov     t,a             ; 0243 - t=0    timer clear
+
+; Start matrix scan
+; r7=r4&c0h
+X0244: mov     a,r4            ; 0244 - a=r4
+       anl     a,#0c0h         ; 0245 - a=a&c0h        BZ=_,CLK=_,DAT=L:
+       mov     r7,a            ; 0247 - r7=r4&c0h      r7=bus-current
+       jf1     X0253           ; 0248 - jump if F1==1 (p1/p2)
+
+; F1==0
+       cpl     f1              ; 024a - F1=1(=~F1)
+       mov     r2,#03fh        ; 024b - r2=3fh         scan code seed
+       mov     r3,#001h        ; 024d - r3=01h         row mask
+       mov     r1,#015h        ; 024f - r1=15h         last key state
+       jmp     X0263           ; 0251 - scan matrix p1 row
+
+; F1==1
+X0253: clr     f0              ; 0253 - F0=0
+       clr     f1              ; 0254 - F1=0
+       mov     r2,#077h        ; 0255 - r2=77h         scan code seed
+       mov     r3,#002h        ; 0257 - r3=02h
+       mov     r1,#01ch        ; 0259 - r1=1ch         last key state
+       jmp     X0287           ; 025b - Scan matrix p2 row
+;
+; INPUT:    F1=0
+X025d: cpl     f1              ; 025d - F1=~F1=1
+       call    X002c           ; 025e - receive/send data
+       clr     f1              ; 0260 - F1=0
+       jmp     X0244           ; 0261 -
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; scan matrix p1 row
+; INPUT: F1=1, r1=15h, r2=3fh, r3=01h, r7=r4&c0h
+;       (r1): last state
+;
+; r0:col, r7:bus-current, r3:row(drive H), r4=bus-default
+;
+; $15: bit7
+;
+; bus:  xxxS Gccc
+;
+X0263: mov     a,#008h         ; 0263 - a=8 LOOP>>>
+       mov     r0,a            ; 0265 - r0=08h =column
+       orl     a,r7            ; 0266 - a=08h|r7
+       mov     r7,a            ; 0267 - r7=a     =xxxx  1ccc(G:1 column:ccc) r7=P1 value
+X0268: dec     r7              ; 0268 - LOOP>> r7--
+       mov     a,r7            ; 0269 - a=r7
+       outl    bus,a           ; 026a -                        [select column]
+       orl     bus,#010h       ; 026b - sensor out=H           [sensor clamp=H]???
+       mov     a,r3            ; 026d - a=r3                   current row
+       outl    p1,a            ; 026e - drive line with H      [select row]
+       mov     a,r4            ; 026f - a=r4                   bus default value
+       outl    bus,a           ; 0270 -                        [revert bus default]
+       orl     bus,#008h       ; 0271 - D3:H sensor-G          [strobe]??? hold? clean Sensor?
+       anl     p1,#000h        ; 0273 -                        [unselect row]
+
+       jnt0    X02ab           ; 0275 - sensor out==0
+; Sensor==1[key is on]
+       mov     a,@r1           ; 0277 - a=$(r1); r1=15...  last key state
+       jb7     X02e5           ; 0278 - jump if a:bit7==1(off) press
+; a:bit7==0(last key state is on)  same as last
+;On->On
+
+
+; Go to next column
+X027a: rl      a               ; 027a - a=a<<1
+       mov     @r1,a           ; 027b - (r1)=a; (r1)=(r1)<<1   next col of last key state
+X027c: dec     r2              ; 027c - r2--                   [key index of scan code table]
+       djnz    r0,X0268        ; 027d - <<LOOP(8)              [next col]
+
+       dec     r1              ; 027f - r1--   15,14,13,12,11,10,0F,0E? [last key state]
+       mov     a,r3            ; 0280 -
+       rl      a               ; 0281 -
+       mov     r3,a            ; 0282 - r3=r3<<1 next row
+       jb0     X0230           ; 0283 - jump if a:bit0==1  scan end(goto Main loop)
+       jmp     X0263           ; 0285 - <<<LOOP                [next row]
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Scan matrix p2 row(F1==1)
+; INPUT: F0=0, F1=0, r1=1ch, r2=77h, r3=02h, r7=bus-current, r4=bus-default
+;
+; r0:col, r7:bus-current, r3:row(drive H), r4=bus-default
+;   key index: 77h-
+X0287: mov     a,#008h         ; 0287 - a=8    LOOP>>
+       mov     r0,a            ; 0289 - r0=8
+       orl     a,r7            ; 028a - a=a|r7
+       mov     r7,a            ; 028b - r7=a
+X028c: dec     r7              ; 028c - r7-- LOOP>>
+       mov     a,r7            ; 028d - a=r7
+       outl    bus,a           ; 028e -                        [select column]
+       mov     a,r4            ; 0293 -                        bus default value
+       outl    bus,a           ; 0294 -                        [revert bus default]
+       orl     bus,#008h       ; 0295 -                        [strobe]
+       anl     p2,#000h        ; 0297 - p2=00h                 [unselect row]
+       jnt0    X02ab           ; 0299 - jump if sensor out==0(key is on)
+; sensor==1(key is off)
+       mov     a,@r1           ; 029b - a=(r1)                 [last key state]
+       jb7     X02e5           ; 029c - jump if a:bit7==1(off)  press
+
+; a:bit7==0(last key state is on)
+X029e: rl      a               ; 029e - a=a<<1
+       mov     @r1,a           ; 029f - (r1)=a                 [next last key bit]
+X02a0: dec     r2              ; 02a0 - r2--(77h)
+       djnz    r0,X028c        ; 02a1 - jump if r0--!=0 <<LOOP(8)
+       dec     r1              ; 02a3 - r1--                   [next last key byte]
+       mov     a,r3            ; 02a4 -
+       rl      a               ; 02a5 -
+       mov     r3,a            ; 02a6 - r3=r3<<1   [next row]??
+       jb0     X025d           ; 02a7 -
+       jmp     X0287           ; 02a9 - <<LOOP
+
+;
+; debouncing and change last key state
+;
+; sensor out==0(press; key is on)
+;
+; debouncing
+X02ab: call    X030d           ; 02ab - a=0(sensor out=1), ffh(sensor out=0)   [Sense key]
+       jz      X02f8           ; 02ad - if a==0(key is off)
+       call    X030d           ; 02af -                                        [Sense key]
+       jz      X02f8           ; 02b1 - if a==0(key is off)
+
+; Sensor==0(a=ffh; press)
+       mov     a,@r1           ; 02b3 - a=(r1) last key state????
+       jb7     X02ca           ; 02b4 -
+
+;
+; [release](off->on)
+;
+; last:bit7==0(off) && sensor=0(on)
+       orl     a,#080h         ; 02b6 - 0:on   1:off
+       rl      a               ; 02b8 -
+       mov     @r1,a           ; 02b9 - (r1)=(r1)<<1   next column
+       call    X0325           ; 02ba - key configure flag
+                                ;        (a:bit1=repeat enable, a:bit0=break enable)
+; if keyconf:bit0==1 then set release flag
+       jb0     X02fd           ; 02bc - r2=r2|80h          [press flag]
+; if keyconf:bit1==1 then set repeat
+       jb1     X02e1           ; 02be - r5=repeat delay    [repeat]
+
+; get scan code and queue it into buffer
+X02c0: call    translate034E   ; 02c0 - a=scancode
+       call    X0339           ; 02c2 - queue data to buffer
+       call    X0303           ; 02c4 -                    [r1=a=address of last key state]
+X02c6: jf1     X027c           ; 02c6 - next col(F1==1)
+       jmp     X02a0           ; 02c8 - next col(F1==0)
+
+;
+; [hold key]
+;
+; last key is on and sensor==0(on)     (on->on)
+X02ca: rl      a               ; 02ca -
+       mov     @r1,a           ; 02cb - (r1)=(r1)<<1
+       call    X0325           ; 02cc - key configure flag
+                                ;        (a:bit1=repeat enable, a:bit0=break enable)
+; repeat:flag
+       jb1     X02d4           ; 02ce -                    [repeat]
+
+; if repeat:flag(bit1)==0  (no repeat)
+X02d0: call    X0303           ; 02d0 - r1=r2&0fh+0eh      address of last key state
+       jmp     X02c6           ; 02d2 - goto next col
+
+; if flag:bit1==1  (repeat)
+X02d4: jf0     X02dd           ; 02d4 -
+
+; F0==0
+       cpl     f0              ; 02d6 - F0=~F0=1
+       djnz    r5,X02d0        ; 02d7 -
+       mov     r5,#007h        ; 02d9 - r5=07h             repeat interval
+       jmp     X02c0           ; 02db - send scan code
+
+; F0==1
+X02dd: mov     r5,#028h        ; 02dd - r5=28h             repeat delay(for first repeat)
+       jmp     X02d0           ; 02df -
+;
+X02e1: mov     r5,#028h        ; 02e1 - r5=28h             repeat delay(for first repeat)
+       jmp     X02c0           ; 02e3 - send scan code
+
+
+;
+; debouncing and change last key state: press
+;
+;   INPUT: (r1): last key status
+;
+; (r1):bit7==1(last key is on) &&  Sensor==1(key is off)  [release]
+X02e5: call    X030d           ; 02e5 - a=0(sensor out=1), ffh(sensor out=0)   [Sense key]
+       jnz     X02f8           ; 02e7 -
+       call    X030d           ; 02e9 -                                        [Sense key]
+       jnz     X02f8           ; 02eb - \_debouncing
+; Sensor==1(a=0)                                                                [Debounced]
+
+;
+; on->off [release]
+;
+       mov     a,@r1           ; 02ed - a=(r1) RAM
+       anl     a,#07fh         ; 02ee - a=a&7fh        last state=0(0:on 1:off)
+       rl      a               ; 02f0 - a=a<<1
+       mov     @r1,a           ; 02f1 - (r1)=a
+;
+       call    X0325           ; 02f2 - key configure flag
+                                ;        (a:bit1=repeat enable, a:bit0=break enable)
+       jb0     X02c0           ; 02f4 - goto translate if a:bit0==1
+       jmp     X02d0           ; 02f6 -
+
+; go to next col scan   Sensor==1
+X02f8: mov     a,@r1           ; 02f8 -
+       jf1     X027a           ; 02f9 - goto next col scan(p1) if F1==1        [Next column]
+       jmp     X029e           ; 02fb - goto next col scan(p2) else            [Next column]
+
+;
+; add press flag(bit8)
+; r2=key index
+X02fd: mov     a,r2            ; 02fd -                                        [key index]
+       orl     a,#080h         ; 02fe -
+       mov     r2,a            ; 0300 - r2=r2|80h  **press flag**
+       jmp     X02c0           ; 0301 -
+
+; Address of last key state
+; INPUT: r2=key index
+; OUTPUT: r1=(r2>>3)&0fh+0eh    = address of last key state
+X0303: mov     a,r2            ; 0303 - a=r2   key index
+       rr      a               ; 0304 -
+       rr      a               ; 0305 -
+       rr      a               ; 0306 - a= a>>3
+       anl     a,#00fh         ; 0307 - a= a & 0fh
+       add     a,#00eh         ; 0309 - a= a + 0eh
+       mov     r1,a            ; 030b - r1=a
+       ret                     ; 030c -
+
+;;;;;;;;;;;;;;;;;;;;;;;
+; Sense key
+;   INPUT: r7: bus-current, F1:0(p2),1(p1) r4=bus-default, r3=row
+;   RETURN: a=0xff(sensor out=0, press), 0(sensor out=1, release)
+;
+X030d: mov     a,r7            ; 030d - r7: bus-current
+       outl    bus,a           ; 030e -                            [Select column]
+       orl     bus,#010h       ; 030f -                            [Charge: D4]
+       mov     a,r3            ; 0311 - r3: row(drive) select      p1(F1=1)/p2(F1=0) setting
+       jf1     X0317           ; 0312 -
+; F1==0
+       outl    p2,a            ; 0314 - set p2                     [Select row]
+       jmp     X0318           ; 0315 -
+; F1==1
+X0317: outl    p1,a            ; 0317 - set p1                     [Select row]
+
+X0318: mov     a,r4            ; 0318 - r4: bus-default
+       outl    bus,a           ; 0319 - set bus
+       clr     a               ; 031a - a=0
+       orl     bus,#008h       ; 031b -                            [Strobe: D3]
+       anl     p1,#000h        ; 031d - clear p1                   [Unselect row]
+       anl     p2,#000h        ; 031f - clear p2                   [Unselect row]
+
+       jt0     X0324           ; 0321 - sensor out==1
+sensor out==0
+       cpl     a               ; 0323 -  a=0xff                    [press(on)]
+sensor out==1
+X0324: ret                     ; 0324 -  a=0                       [release(off)]
+;
+; End of Main
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; key configure flags
+;
+; INPUT: r2=key index(p1:-3fh, p2:-77h)    (aaaaaaii)
+: OUTPUT: a=Key configure 2-bit flags;  bit0 and 1 are only valid. (------rb)
+;
+:   Key configure flags are retained in RAM($22-3F) and
+;   Key configure flags use 2bit per key so that a byte can has flags of four key like:
+;       bit 7   6   5   4   3   2   1   0
+;           3r  3b  2r  2b  1r  1b  0r  0b
+;   where r=repeat enable, b=break code(release) eanble
+;
+X0325: mov     a,r2            ; 0325 - a=r2           index
+       rr      a               ; 0326 -
+       rr      a               ; 0327 - a=a>>2         bit7-2 of index(aaaaaa)
+       add     a,#022h         ; 0328 - a=a+22h        $22+aaaaaa
+       mov     r1,a            ; 032a - r1=a
+       mov     a,@r1           ; 032b - a=(r1)         $22-3F(ignored bit7,bit6)
+       mov     r1,a            ; 032c - r1=a           r1=($22-3F) ????
+       mov     a,r2            ; 032d - a=r2           index
+       anl     a,#003h         ; 032e - a=a&03h        a=bit0,bit1 of index
+       xch     a,r1            ; 0330 - a<->r1         r1=bit0,bit1 of index, a=($22-3F)
+       inc     r1              ; 0331 - r1++           =1-4
+X0332: djnz    r1,X0335        ; 0332 - while --r1>0
+       ret                     ; 0334 -
+
+; place flags of the key on bit0 and 1
+X0335: rr      a               ; 0335 -
+       rr      a               ; 0336 - a=a>>2; a=$22-3F
+       jmp     X0332           ; 0337 -
+
+;
+; Queue data to bottom of outgoing buffer(bank1:r5,r6,r7)
+; INPUT: a=data, r2=???
+; OUTPUT: r2=r2&07h
+; a->r5->r6->r7
+X0339: sel     rb1             ; 0339 -   switch to bank1
+       inc     a               ; 033a -   a++
+       xch     a,r5            ; 033b -   a<->r5
+       jz      X0348           ; 033c -
+       xch     a,r5            ; 033e -
+       xch     a,r6            ; 033f -
+       jz      X0348           ; 0340 -
+       xch     a,r6            ; 0342 -
+       xch     a,r7            ; 0343 -
+       jz      X0348           ; 0344 -
+       mov     r7,#0ffh        ; 0346 -   buffer overflow
+X0348: sel     rb0             ; 0348 -   switch to bank0
+       mov     a,r2            ; 0349 -   a=r2
+       anl     a,#07fh         ; 034a -   a=a&7fh
+       mov     r2,a            ; 034c -   r2=a
+       ret                     ; 034d -
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Translate key index into scancode
+;
+; INPUT: r2=keyindex [bit7:release flag(1:release/0:press), bit6-0:index]
+; OUTPUT: a=scancode
+translate034E:
+       mov     r1,#021h        ; 034e -
+       mov     a,@r1           ; 0350 - a=$21  $21:bit6,5,4 = traslate table
+       anl     a,#0f0h         ; 0351 - a=a & f0h
+       xrl     a,#020h         ; 0353 - a=a ^ 20h      $21:bit5(0010 0000) 0010 xxxx => table1
+       jz      X0361           ; 0355 - if a==0        read table1     (6019273 50-key)
+       xrl     a,#010h         ; 0357 - a=a ^ 10h      $21:bit4(0001 0000) 0011 xxxx => table2
+       jz      X0370           ; 0359 -                read table2     (6019284 62-key)
+       xrl     a,#070h         ; 035b - a=a & 70h      $21:bit6(0111 0000) 0100 xxxx => table2
+       jz      X0370           ; 035d -                read table2     (6019303 77-key)
+       mov     a,r2            ; 035f -                else use r2(keyindex) instead of scancode
+       ret                     ; 0360 -
+; table1(8x7=56)
+X0361: mov     a,r2            ; 0361 - keyindex
+       anl     a,#07fh         ; 0362 -
+       add     a,#078h         ; 0364 - table1
+; read table
+X0366: movp3   a,@a            ; 0366 - read scancode from table a=scan code
+       xch     a,r2            ; 0367 - a=keyindex, r2=scancode
+       jb7     X036c           ; 0368 - if keyindex:bit7==1 [relase event]
+       xch     a,r2            ; 036a - a=scancode, r2=keyindex
+       ret                     ; 036b -
+; release flag
+X036c: xch     a,r2            ; 036c -
+       orl     a,#080h         ; 036d - [[[[[release flag(bit7)]]]]]
+       ret                     ; 036f - a: scan code
+; table2(8X10=80)
+X0370: mov     a,r2            ; 0370 -
+       anl     a,#07fh         ; 0371 -
+       add     a,#0b0h         ; 0373 - table2
+       jmp     X0366           ; 0375 - read table
+
+
+; maybe 'salt' to make sum of program memory 'zero'(at 0222h)
+       db      0b6h                                    ; 0377 6
+
+
+;;;;;;;;;;;;;;;;;;
+;
+; Scancode table
+;
+
+;;;;;;;;;;;;;;;;;;
+; Used for 6019273                                        Add  Key              Parameter RAM
+table1:        db      03fh,037h,03ah,036h,02ah,035h,022h,023h ; 0378
+       db      03bh,02bh,039h,031h,032h,029h,021h,0ffh ; 0380
+       db      033h,038h,0ffh,030h,028h,0ffh,020h,0ffh ; 0388
+       db      017h,01dh,01ch,015h,00ch,00dh,004h,005h ; 0390
+       db      00fh,01fh,01bh,013h,014h,00bh,003h,0ffh ; 0398
+       db      00eh,01ah,019h,012h,009h,00ah,001h,002h ; 03a0
+       db      016h,01eh,018h,010h,011h,008h,000h,0ffh ; 03a8
+
+;;;;;;;;;;;;;;;;;;
+; Used for 6019284 and 6019303                            Add  Key              Parameter RAM
+table2:        db      02fh,03dh,03ch,02dh,01dh,01ch,00ch,00eh ; 03b0 Enter ... BS     $22, $23
+       db      03fh,042h,03bh,02bh,02ch,01bh,01fh,00dh ; 03b8 RAlt ...         $24, $25
+       db      039h,03ah,029h,02ah,002h,003h,00ah,00fh ; 03c0 ...              $26, $27
+       db      038h,037h,028h,027h,017h,001h,008h,009h ; 03c8 ...              $28, $29
+       db      040h,036h,025h,026h,015h,016h,011h,012h ; 03d0 ...              $2a, $2b
+       db      035h,034h,023h,024h,013h,014h,01ah,010h ; 03d8 ...              $2c, $2d
+       db      03fh,032h,033h,022h,021h,006h,005h,019h ; 03e0 LAlt ...         $2e, $2f
+       db      031h,041h,03eh,030h,020h,004h,000h,018h ; 03e8 Reset ... 1      $30, $31
+       db      071h,076h,075h,066h,055h,056h,045h,046h ; 03f0 Used for 77-key  $32, $33
+       db      077h,067h,074h,064h,065h,054h,0ffh,044h ; 03f8 Used for 77-key  $34, $35
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+
+;
+;      symbol equates
+;
+;  these are symbols from the control
+;  file that are referenced in the code
+;
+jump_table     equ     0fah
+;
+       end