forked from tmk/tmk_keyboard
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ibm4704.txt
1696 lines (1437 loc) · 54.3 KB
/
ibm4704.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
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.ca/?p=894
http://imgur.com/a/LaABs
Brochure:
http://ed-thelen.org/comp-hist/IBM-ProdAnn/4700.pdf
4704 Keyboard Protocol
======================
On powering up keyboard sends keyboard ID; A3h for 6019284(62-key), for example.
After that the keyboard enters FC command mode and waits for parameter data from host
so that it doesn't send any scancode until you send 'FF'(End of FC command mode).
Keyboard ID
-------------------------------
Model 100 50-key A2h
Model 200 62-key A3h
Model 300 77-key A4h
Model 400 107-key A5h
Japanese/Chinese 102-key A6h
Connector
---------
Keyboard Plug from front
DSUB-9
-------------
\ N 2 3 4 5 /
\ N N N N /
---------
2 GND
3 VCC 5V
4 DATA
5 CLOCK
N No connection/No pin.
Keyboard to Host
----------------
Data bits are LSB first and Pairty is odd. Clock has around 60us high and 30us low part.
____ __ __ __ __ __ __ __ __ __ _______
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.(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.
____ __ __ __ __ __ __ __ __ __ ________
Clock \______/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
^ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___
Data ____|__/ X____X____X____X____X____X____X____X____X____X \___
| Start 0 1 2 3 4 5 6 7 P Stop
Request by host
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.
Host wirtes a bit while Clock is hi and Keyboard reads while low.
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| -| =|**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| ,| ,| /|**2|Shift |
|-----------------------------------------------------------|
|Reset|blk|Alt | Space |Alt |blk|Enter|
`-----------------------------------------------------------'
+----------+---------------------+----------+----------+
|` 00|PD1 04|Caps 20|LShift 30|Reset 31|
|1 18|q 05|a 21|<> 3E|Rblank 41|
|2 19|w 06|s 22|z 32|Alt 3F|
|3 1A|e 13|d 23|x 33|Space 40|
|4 10|r 14|f 24|c 34|Alt 3F|
|5 11|t 15|g 25|v 35|Lblank 42|
|6 12|y 16|h 26|b 36|Enter 2F|
|7 08|u 17|j 27|n 37| |
|8 09|i 01|k 28|m 38| |
|9 0A|o 02|l 29|, 39| |
|0 0F|p 03|; 2A|. 3A| |
|- 1F|¢ 1B|' 2B|/ 3B| |
|= 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.
NOTE: When break code is enabled the key sends scancode with setting 7th bit on press
and without it on release. That is, '`' sends 80h on press and 00h on release.
Keyboard command
----------------
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
-----------------
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 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)
------------------------
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' to exit this mode.
With Alps models you need to send 'FC' command to enter this mode.
Data sent from host:
bit: 7 6 ... 0
en | |
| `-----`--- scan code
`------------- enable bit(0: enable repeat, 1: enable break)
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 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