X-Git-Url: https://git.friedersdorff.com/?a=blobdiff_plain;f=converter%2Fibm4704_usb%2Fibm4704.txt;h=3e983848d3b5e42670e8b9319da72a0daf6eabd4;hb=3e8289b53ce929484651fc065fb5f718e4e3ae21;hp=c17d172af1dc5b0652c45a8dc3ac0979972a5ad3;hpb=188ab49dd3467217a59fea59995259df69bbb78e;p=max%2Ftmk_keyboard.git diff --git a/converter/ibm4704_usb/ibm4704.txt b/converter/ibm4704_usb/ibm4704.txt index c17d172a..3e983848 100644 --- a/converter/ibm4704_usb/ibm4704.txt +++ b/converter/ibm4704_usb/ibm4704.txt @@ -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= ; select column S0-2 + D4=1 ; Prepare sensor(Charge?) + P1/P2= ; select row + D0-4= ; 00010(bus=c2h) + D3=1 ; Strobe + P1/P2=0 ; unselect row + read T0 ; see key state + + at 01afh: + D0-2= + 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 - > + 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 - <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 - 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 - <> +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 - <=0 + call X00d8 ; 015b - Error: FD and cont. [Out of bound Error: FD] +X015d: jmp X010b ; 015d - <>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 - <> 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 - <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 - <> + 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 <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