]> git.friedersdorff.com Git - max/tmk_keyboard.git/blobdiff - converter/ibm4704_usb/ibm4704.txt
lufa: Fix comment on INTERRUPT_CONTROL_ENDPOINT
[max/tmk_keyboard.git] / converter / ibm4704_usb / ibm4704.txt
index c17d172af1dc5b0652c45a8dc3ac0979972a5ad3..3e983848d3b5e42670e8b9319da72a0daf6eabd4 100644 (file)
@@ -1,15 +1,28 @@
-4704 Keyboard
-=============
-Keyboard Models:
-    Model 100 6019273 50-key (grid layout)
-    Model 200 6019284 62-key Alpha(60% layout)
-    Model 300 6019303 77-key Expanded Alpha
-    Model 400 6020218 107-key Full key
+IBM 4704 Keyboard Analysis - 6019284(62-key)
+============================================
+2013/02/09, 2019/07/12
+
+IBM 4704 Keyboard
+=================
+IBM capacitive switch models:
+    6019273 Model 100 50-key (grid layout)      http://kishy.ca/?p=894
+    6019284 Model 200 62-key Alpha(60% layout)  http://kishy.ca/?p=894
+    6019303 Model 300 77-key Expanded Alpha     http://deskthority.net/photos-f62/ibm-6019303-t8502.html
+    6020218 Model 400 107-key Full key          http://kishy.ca/?p=894
+
+Alps switch(vintage Green) models:
+    5954339 Japanese 102-key    http://deskthority.net/post87127.html#p87127
+    6112883 Japanese 102-key    http://geekhack.org/index.php?topic=52888.msg1194489#msg1194489
+    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
@@ -18,9 +31,18 @@ http://ed-thelen.org/comp-hist/IBM-ProdAnn/4700.pdf
 
 4704 Keyboard Protocol
 ======================
-On powering up the keyboard sends keyboard id; A3h for 6019284(62-key), for example.
-After that firmware 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).
+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
+    Model 200 62-key            A3h
+    Model 300 77-key            A4h
+    Model 400 107-key           A5h
+    Japanese/Chinese 102-key    A6h
 
 
 Connector
@@ -43,18 +65,19 @@ Keyboard to Host
 ----------------
 Data bits are LSB first and Pairty is odd. Clock has around 60us high and 30us low part.
 
-            ____      __   __   __   __   __   __   __   __   __   ________
-    Clock       \____/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/
-                 ____ ____ ____ ____ ____ ____ ____ ____ ____ ____    
+            ____       __   __   __   __   __   __   __   __   __   _______
+    Clock       \_____/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/
+                 ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
     Data    ____/    X____X____X____X____X____X____X____X____X____X________
                 Start   0    1    2    3    4    5    6    7    P  Stop
 
 Start bit:  can be long as 300-350us.
 Inhibit:    Pull Data line down to inhibit keyboard to send.
-Timing:     Host reads bit while Clock is hi.
+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.
@@ -66,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.
@@ -74,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|
     `-----------------------------------------------------------'
@@ -103,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.
@@ -113,30 +137,41 @@ NOTE: When break code is enabled the key sends scancode with setting 7th bit on
 and without it on release. That is, '`' sends 80h on press and 00h on release.
 
 
-keyboard command
+Keyboard command
 ----------------
-    FF  Soft Reset(0008h)
-    FE  Resend(00e8h)
-    FD  Buzzer stop?(00edh)
-    FC  Set Key flag(00f6h)
-    FB  Soft Reset(0008h)
-    FA  Reset(0000h)
-    
+Keyboard accepts these commands from host.
+
+        Description                             Entry point
+    -----------------------------------------------------------
+    FF  Soft Reset                              0008h
+    FE  Resend                                  00e8h
+    FD  Buzzer(emits a short beep)              00edh
+    FC  Set Key Flag                            00f6h
+    FB  Soft Reset                              0008h
+    FA  Reset                                   0000h
+
 
 Keyboard response
 -----------------
-    FF  Not exist. [Outgoing buffer cannot have FFh(00h in fact)]
-    FE  Overflow(key event/receive data)        at 00c5h, 0346h
-    FE  Memory test error                       at 0224h
-    FD  Command out of bound                    at 00d8h
+Keyobard sends these bytes to host.
+
+        Description                             Entry point
+    -----------------------------------------------------------
+    FE  Overflow(key event/receive data)        00c5h, 0346h
+        Memory test error                       0224h
+    FD  Command out of bound                    00d8h
         Key out of bound
-    7E  Read/Parity error in receive from host  at 00bch
+    7E  Read/Parity error in receive from host  00bch
+    80-FB? scan code(make)
+    00-7B? scan code(break)
+    note: Alps model spits scan code 7B(FB) at least.
 
 
-Set Key flag command(FC)
+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:
 
@@ -145,16 +180,1517 @@ Data sent from host:
          |   `-----`--- scan code
          `------------- enable bit(0: enable repeat, 1: enable break)
 
-    00-77   Enable repeat(78-7F: invalid scancode)
-    80-F7   Enable break(F8-FF: invalid scancode)
+    00-7B   Enable repeat
+    80-FB   Enable break
     FE      Resend(011ah) no need to use
     FF      End(0114h) exits FC command mode.
 
 Response from keyboard:
     FD      Out of bound - Invalid scancode
+    --      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
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
 
-    FC 80 81 ... F7 FF
 
+;
+;      symbol equates
+;
+;  these are symbols from the control
+;  file that are referenced in the code
+;
+jump_table     equ     0fah
+;
+       end