-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path8048_XT_INTERN.TEXT
841 lines (705 loc) · 46.8 KB
/
8048_XT_INTERN.TEXT
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
8048 AT INTERN 4584751
========================
Commented Intel 8048 disassembly of the IBM 83-key Type-2 Model F (XT) keyboard ROM
A. Tarpai 2018
(Questions & comments are welcome to tarpai76 at gmail)
This file has been downloaded from
http://www.halicery.com/8042/8048_XT_INTERN.TEXT
Because of this analysis was done after the 84-key AT ROM (1503099), much of the general info can be found there. The two keyboards are very similar electronically. The main purpose was to confirm/expand the knowledge on that mysterious silver, SENSE AMPLIFIER IC ("SA"). Only the most important figs for reading the comments are here. The IBM PC/XT keyboard is this "compact", tough keyboard from 1981 with capacitive technology and 83 keys, numbered after IBM as:
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ __________ __________ __________
| 59 || 60 | | 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9 || 10 || 11 || 12 || 13 || 14 || 69 || 70 |
|____||____| |____||____||____||____||____||____||____||____||____||____||____||____||____||__________||__________||__________|
____ ____ _______ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ _____ ______ ____ ____ ____ ____
| 61 || 62 | | 15 || 16 || 17 || 18 || 19 || 20 || 21 || 22 || 23 || 24 || 25 || 26 || 27 || 28 || 71 || 72 || 73 || 74 |
|____||____| |_______||____||____||____||____||____||____||____||____||____||____||____||_____|| ||____||____||____||____|
____ ____ ________ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ | | ____ ____ ____ ____
| 63 || 64 | | 29 || 30 || 31 || 32 || 33 || 34 || 35 || 36 || 37 || 38 || 39 || 40 || 41 || || 75 || 76 || 77 || |
|____||____| |________||____||____||____||____||____||____||____||____||____||____||____||____||______||____||____||____|| |
____ ____ _____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ _______ ______ ____ ____ ____ | 78 |
| 65 || 66 | | 42 || 43 || 44 || 45 || 46 || 47 || 48 || 49 || 50 || 51 || 52 || 53 || 54 || 55 || 79 || 80 || 81 || |
|____||____| |_____||____||____||____||____||____||____||____||____||____||____||____||_______||______||____||____||____|| |
____ ____ __________ _________________________________________________________ ___________ __________ __________ | |
| 67 || 68 | | 56 || 57 || 58 || 82 || 83 || |
|____||____| |__________||_________________________________________________________||___________||__________||__________||____|
Schematics
==========
The firmware corresponds with the Logic Diagram of the Type-2 PC/XT Keyboard from IBM Ref Manuals. 12 drive lines are connected directly to the 8048 (port P1 and P2 HI), while P2 LO controls the SA:
8 col
- -+-+-+-+-+-+-+-+-
- -+-+-+-+-+-+-+-+-
P1 - -+-+-+-+-+-+-+-+-
+---------------------------> - -+-+-+-+-+-+-+-+-
| - -+-+-+-+-+-+-+-+- 12 row
| - -+-+-+-+-+-+-+-+-
| - -+-+-+-+-+-+-+-+-
| - -+-+-+-+-+-+-+-+-
| - -+-+-+-+-+-+-+-+-
| P2 HI - -+-+-+-+-+-+-+-+-
| +----------------> - -+-+-+-+-+-+-+-+-
| | - -+-+-+-+-+-+-+-+-
| |
| | | | | | | | | |
| | P2 LO - +-----------------------+
| +-----------------> - | SENSE AMPLIFIER |
| | 3-to-8 - | MUX IC |
| | +-----------------------+
| | | Q out
| | |
| | _
| | \____ low
| |
| | |
| | +-->--+ +5V---+------->-------+
| | | | | |
+------------------------------------------------------------------------+ |
| P1 P2 P23 T1 DB5 INT| <------+------- KB DATA (pulled low by KB)
| 8048 |
| MICROCOMPUTER DB6 T0 | <------+------- KB CLK (REQIN/REQOUT when pulled low)
+------------------------------------------------------------------------+ REQIN |
| |
+5V---+-------->------+
REQOUT
The XT's SENSE AMPLIFIER
========================
The timing diagram according to the code in the ROM shows similarities with the AT (see 1503099). Opposed to the AT there is no variable threshold used: each sensing is driven with sensitivity threshold "3". Drive is separately controlled. The enable SA, drop drive pulse, read SA output appears in the same sequence:
read
T1
1 2 3 4 5 6 7 8
| | | | | | | |
______ ___|____|______
\_________________________/ | | SA LATCH RESET (DB7)
| |
___________ ___________________|____|______
___________\____/ | \_|______ SA CLOSED/OUTPUT Q (P23/T1)
|
_________|
__________________________/ \___________ DRIVE SELECT (P1/P2HI)
___________ _________ __________________________
___________X_________3__________________________ SENSE SELECT (P2_0..3)
mux thr
This is done for each sensor writing P2_0_3 twice:
1. clear RESET
2. clear Q and write SENSE SELECT with 0..7
3. pull Q high: SA latches the mux address
4. keep Q high and write SENSE SELECT with "3"
5. write DRIVE SELECT (charge)
6. pull RESET high: SA latches threshold value and enabled
7. Now clear DRIVE SELECT (discharge): drive pulse goes low
8. sample T1 for low (=SA CLOSED, depressed button)
(On RESET P1, P2 set FFh high)
Ports of the 8048
=================
7 6 5 4 3 2 1 0
+--------+--------+--------+--------+--------+--------+--------+--------+
| | CLK | DATA | | | | DB
+--------+--------+--------+--------+--------+--------+--------+--------+
| |
T0 INT
7 6 5 4 3 2 1 0
+--------+--------+--------+--------+--------+--------+--------+--------+
| DRIVE SELECT LO | P1
+--------+--------+--------+--------+--------+--------+--------+--------+
7 6 5 4 3 2 1 0
+--------+--------+--------+--------+--------+--------+--------+--------+
| DRIVE SELECT HI | Q | SENSE SELECT | P2
+--------+--------+--------+--------+--------+--------+--------+--------+
|
T1
The matrix scanning loop
========================
For each row all of the 8 columns are sampled and the result is stored in R4, the "Sense Word". The controller drives a double pulse to confirm a changed row state (Double Sense). When these readings differ, it is considered noise and throws it away, and keeps the previous state of the row.
Flow chart
==========
R2: Row/Col counter
R3: typematic counter (fix Delay/Rate used)
R5: scancode of the typematic key
RESET <---------------------------------------------------------------+
| |
R2=00 |
| |
+------>------ R2=0? ------ Init |
| | | |
| | Wait Timer |
| | | |
| +----<------+ |
| | |
| End/beginning ------------ REQIN? -----------> Run BAT |
| of scan? | | |
| | | OK? --> put AA into FIFO --->--+
| | Transmit one scancode | |
| | from FIFO +---------------------->------+
| | |
| +-------<--------------+
| |
| Scan row R2
| |
| For all columns:
| changed? ---------------------------------------------+
| | |
| | Double Sense
| | update row state
| | |
| | Push? ---------------+
| held? ---------+ | |
| | | | Put makecode
| | DEC R3*--------+ | into scancode FIFO
| | expired? | | |
| | | | | Put makecode into R5
| | | Put makecode R5 | Load Delay into R3
| | | into scancode FIFO | |
| | | | Put breakcode |
| | | Load Rate into R3 into scancode FIFO |
| | | | | |
| | | | R5 released? --+ |
| | | | | | |
| | | | | Clear R5 |
| | | | | | |
| +-----<-------+----<------+------------<----------+------<---+-----<--+
| |
| DEC row
| |
+------<---------+
*: once per full scan, i.e. multiple keys held keep the same rate
RAM map for this firmware
=========================
64 bytes of RAM
+----------------------------------------+
| $3F |
| ... 12 bytes MATRIX MAP |
| $34 |
| |
| $30 |
| ... 16+1 byte FIFO |
| $20 |
+----------------------------------------+
| $1F R7' |
| $1E R6' |
| $1D R5' |
| $1C R4' |
| $1B R3' Flag for Typematic counter |
| $1A R2' Typematic counter |
| $19 R1' tmp for FIFO out |
| $18 R0' FIFO PTR RB1 |
+----------------------------------------+
| STACK |
+----------------------------------------+
| R7 |
| R6 SENSE SELECT |
| R5 Typematic makecode |
| R4 Sense Word |
| R3 Diff Word (complemented) |
| R2 Row/Col Counter |
| R1 MATRIX MAP PTR |
| R0 DRIVE BIT SELECT |
+----------------------------------------+
$1B: Flag for Typematic counter to count full scans. Start of scan clears it, Typematic counter $1A is only decremented when it is zero, then $1B is set.
CPU Flag F0 seems global meaning: cleared after RESET, in BAT, Set in Send A, but cleared in REQIN when reading 'flips', unstable, floating? DATA not connected well? Used as flag in Double Sense
CPU flag F1: FIFO is empty when 0. Then 8048 will also initialize the FIFO and the FIFO PTR (Put FIFO routine)
Opening 4584751.m1
*********************
** RESET **
*********************
0000: 00 NOP
0001: C5 SEL RB0 ; RAM bank0
0002: 15 DIS I ; disable external interrupt
0003: 35 DIS TCNTI ; disable timer/counter interrupt
0004: E5 SEL MB0 ; ROM bank0
0005: 85 CLR F0
0006: A5 CLR F1
0007: 23 DF MOV A,#$DF
0009: 02 OUTL BUS,A ; release CLK and pull DATA low
; _________
; C____/
; ____ bus idle state
; D____\____
000A: 27 CLR A
000B: B8 3F MOV R0,#$3F ; clear 64 bytes of RAM ---+
000D: A0 MOV @R0,A ; with all registers |
000E: E8 0D DJNZ R0,$000D ; -------------------------+
0010: 54 34 CALL $0234 ; -> RETR (to clear all PSW flags? But cleared right after.. "RETR reenables the interrupt input logic"?)
0012: 27 CLR A
0013: AA MOV R2,A ; init R2=00 Row/Col Counter
0014: D7 MOV PSW,A ; clear user flags (CY,AC,F0 and BS)
0015: 62 MOV T,A ; clear Timer
0016: 39 OUTL P1,A ; set all drive lines
0017: 3A OUTL P2,A
0018: 55 STRT T ; start Timer
*****************************************
** MAIN SCANNING LOOP **
** **
*****************************************
; R2 is the Row/Col coordinate for a given sensor, which starts counting down from 60h (96 decimal).
; Each row decrements R2 by 8, or in 8048 language lacking SUB, adds F8h.
; R0 is the given line to drive and goes to P1 or P2.
; We read 12 rows, scanning goes backwards until zero:
;
; HI -> P2 | LO -> P1
; R2 60 58 50 48 | 40 38 30 28 20 18 10 08 <-- Row/Col coordinate
; R0 80 40 20 10 | 80 40 20 10 08 04 02 01 <-- DRIVE
0019: FA MOV A,R2
001A: 96 2D JNZ $002D ; R2 nonzero ->
001C: D5 SEL RB1 ; R2 zero: init start of scan
001D: BB 00 MOV R3,#$00 ; clear $1B (flag to dec typematic $1A)
001F: C5 SEL RB0
0020: B8 01 MOV R0,#$01 ; R0=01 drive select LO
0022: BA 60 MOV R2,#$60 ; R2=60
0024: B9 40 MOV R1,#$40 ; init MATRIX MAP PTR
0026: 42 MOV A,T
0027: 03 4D ADD A,#$4D
0029: E6 26 JNC $0026 ; wait a little for timer..
002B: 27 CLR A ; between full scans
002C: 62 MOV T,A ; reset timer
002D: FA MOV A,R2
002E: D3 08 XRL A,#$08
0030: C6 36 JZ $0036 ; R2=08? ->
0032: D3 68 XRL A,#$68
0034: 96 38 JNZ $0038 ; (there is a TIMER loop between these two)
0036: 54 35 CALL $0235 ; --> R2=08 or 60: Check REQIN, Send from FIFO if any
0038: C9 DEC R1 ; dec MATRIX MAP PTR
0039: F8 MOV A,R0
003A: 77 RR A
003B: A8 MOV R0,A ; rotate R0 DRIVE SELECT: init to 01 -> we start with 80
003C: BE 07 MOV R6,#$07 ; load SENSE SELECT counter
003E: 27 CLR A
003F: AC MOV R4,A ; clear Sense Word R4: row status
0040: BF 08 MOV R7,#$08 ; column counter
0042: FA MOV A,R2
0043: D3 40 XRL A,#$40
0045: 96 49 JNZ $0049
0047: B8 80 MOV R0,#$80 ; R2=40: set R0=80
0049: FA MOV A,R2 ; 60 58 50 48 | 40 38 30 28 20 18 10 08 (the 12 R2 values)
004A: 97 CLR C
004B: 03 B8 ADD A,#$B8 ; R2>=48? -> drive hi
004D: F6 69 JC $0069 ; R2<48? -> drive lo
*****************************************
** SENSE **
** **
*****************************************
7 6 5 4 3 2 1 0
Result in R4 with +---+---+---+---+---+---+---+---+
opposite lsb | | | 1 | | | | | | R4
+---+---+---+---+---+---+---+---+
eg. col 2 active
; drive LO LINES on P1
004F: 98 7F ANL BUS,#$7F ; clear RESET ----------------------------------------+
0051: FE MOV A,R6 |
0052: 3A OUTL P2,A ; clear Q and write SENSE SELECT |
0053: CE DEC R6 ; |
0054: 8A 08 ORL P2,#$08 ; pull Q high |
0056: 23 0B MOV A,#$0B |
0058: 3A OUTL P2,A ; keep Q high and write sens 3 |
0059: F8 MOV A,R0 |
005A: 39 OUTL P1,A ; R0 -> P1 DRIVE SELECT |
005B: 88 80 ORL BUS,#$80 ; pull RESET high |
005D: 99 00 ANL P1,#$00 ; clear drive select: start SENSE |
005F: 56 62 JT1 $0062 ; sample Q |
0061: 1C INC R4 ; low? set bit=pushed/closed sensor |
0062: FC MOV A,R4 |
0063: 77 RR A |
0064: AC MOV R4,A |
0065: EF 4F DJNZ R7,$004F ; do this 8 times ------------------------------------+
0067: 04 80 JMP $0080
; drive HI LINES on P2 HI (guess P1=00)
0069: 98 7F ANL BUS,#$7F ; clear RESET ----------------------------------------+
006B: FE MOV A,R6 |
006C: 3A OUTL P2,A ; write SENSE SELECT and clear Q |
006D: CE DEC R6 |
006E: 8A 08 ORL P2,#$08 ; pull Q high |
0070: F8 MOV A,R0 |
0071: 03 0B ADD A,#$0B ; P2 <- R0 + 0B |
0073: 3A OUTL P2,A ; keep Q high and write sens 3 + P2_HI |
0074: 88 80 ORL BUS,#$80 ; pull RESET high |
0076: 9A 0F ANL P2,#$0F ; clear drive select: start SENSE |
0078: 56 7B JT1 $007B ; sample Q |
007A: 1C INC R4 ; low? set bit=pushed/closed sensor |
007B: FC MOV A,R4 |
007C: 77 RR A |
007D: AC MOV R4,A |
007E: EF 69 DJNZ R7,$0069 ; do this 8 times ------------------------------------+
*****************************
** Double Sense **
*****************************
R4 = present row state
@R1 = previous row state
0080: B6 98 JF0 $0098 ; F0=1? have read nonzero row twice ->
0082: F1 MOV A,@R1 ; F0=0: first row reading
0083: DC XRL A,R4
0084: 96 93 JNZ $0093 ; state change? ->
0086: FC MOV A,R4 ; no, same state:
0087: 96 8F JNZ $008F ; state nonzero? ->
0089: FA MOV A,R2 ; same state and zero:
008A: 03 F8 ADD A,#$F8 ; add F8 = sub 08
008C: AA MOV R2,A
008D: 04 19 JMP $0019 ; --> scan next row
008F: BB FF MOV R3,#$FF ; same non-zero state: set no change on row's Diff word ('1' means no change!)
0091: 04 A7 JMP $00A7 ; R3 = FF and encode, possibly held key ->
0093: 95 CPL F0 ; state change: flip F0
0094: FC MOV A,R4
0095: AB MOV R3,A
0096: 04 3C JMP $003C ; save new state to R3 and -> read row again
0098: 85 CLR F0 ; F0=1, we've read nonzero row twice: clear F0
0099: FC MOV A,R4
009A: DB XRL A,R3 ; compare 1st and 2nd
009B: C6 A1 JZ $00A1 ; same, stable ->
009D: F1 MOV A,@R1 ; 1st and 2nd is different: throw away both sensing
009E: AC MOV R4,A ; if prev is zero -> advance to next row. If not: set Diff Word to FF (no change) and proceed
009F: 04 86 JMP $0086 ;
00A1: F1 MOV A,@R1 ; 1st and 2nd same:
00A2: DC XRL A,R4
00A3: 37 CPL A ; R3 Diff word is OPPOSITE: '1' means no change.
00A4: AB MOV R3,A ; R3 = cpl of changed bits
00A5: FC MOV A,R4
00A6: A1 MOV @R1,A ; update map.. then fall thru to encode
*****************************************
** Change encoding **
** R4 = new state **
** R3 = complemented Diff Word **
*****************************************
We have 4 cases:
prev ~diff state
0 1 0 nothing
0 1 1 push
1 0 0 release
1 0 1 held
00A7: BF 08 MOV R7,#$08 ;
00A9: CA DEC R2 ; dec col --------------------+
00AA: FB MOV A,R3 |
00AB: 12 D1 JB0 $00D1 ; no change? |
00AD: 77 RR A ; change |
00AE: AB MOV R3,A ; |
00AF: FC MOV A,R4 |
00B0: 12 C4 JB0 $00C4 ; -> to push |
00B2: 77 RR A ; 10 release: |
00B3: AC MOV R4,A |
00B4: FA MOV A,R2 |
00B5: E3 MOVP3 A,@A ; load scancode |
00B6: DD XRL A,R5 ; last released? |
00B7: 96 BA JNZ $00BA |
00B9: AD MOV R5,A ; yes: clear R5=00 |
00BA: FA MOV A,R2 ; no |
00BB: E3 MOVP3 A,@A ; load scancode |
00BC: 43 80 ORL A,#$80 ; breakcode |
00BE: 54 20 CALL $0220 ; --> Put 'A' into FIFO |
00C0: EF A9 DJNZ R7,$00A9 ; -----------------------------+
00C2: 04 19 JMP $0019 ; --> next row |
|
00C4: 77 RR A ; 01: push |
00C5: AC MOV R4,A |
00C6: FA MOV A,R2 |
00C7: E3 MOVP3 A,@A ; load scancode |
00C8: AD MOV R5,A ; store in R5: last held key |
00C9: 54 20 CALL $0220 ; --> Put 'A' into FIFO |
00CB: 74 60 CALL $0360 ; --> typematic delay |
00CD: EF A9 DJNZ R7,$00A9 ; -----------------------------+
00CF: 04 19 JMP $0019 ; --> next row |
|
00D1: 77 RR A ; no change: |
00D2: AB MOV R3,A ; |
00D3: FC MOV A,R4 |
00D4: 12 DC JB0 $00DC ; key down? |
00D6: 77 RR A ; 00: do nothing |
00D7: AC MOV R4,A |
00D8: EF A9 DJNZ R7,$00A9 ; -----------------------------+
00DA: 04 19 JMP $0019 ; --> next row |
|
00DC: 77 RR A ; no change, 11 key held |
00DD: AC MOV R4,A |
00DE: 74 63 CALL $0363 ; --> typematic rate |
00E0: EF A9 DJNZ R7,$00A9 ; -----------------------------+
00E2: 04 19 JMP $0019 ; --> Main Loop for next row
>> SUB TEST ROM chksum
00E4: A3 MOVP A,@A ; read page-0
>> SUM ROM
00E5: 69 ADD A,R1 ; sum
00E6: A9 MOV R1,A
00E7: F8 MOV A,R0
00E8: 83 RET
00E9: | 00 00 00 00 00 00 00 | ................
00F0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
***********************
** BAT **
***********************
0100: C5 SEL RB0
0101: 15 DIS I
0102: 35 DIS TCNTI
0103: E5 SEL MB0
0104: 85 CLR F0
0105: A5 CLR F1
0106: 27 CLR A
0107: B8 3F MOV R0,#$3F ; TEST 64 bytes of RAM with FF and 00
0109: 37 CPL A ; ---------------------+
010A: A0 MOV @R0,A ; write FF |
010B: D0 XRL A,@R0 ; read back, same? |
010C: 96 28 JNZ $0128 ; -> err |
010E: A0 MOV @R0,A ; ok, write 00 |
010F: D0 XRL A,@R0 ; read back, same? |
0110: 96 28 JNZ $0128 ; -> err |
0112: E8 09 DJNZ R0,$0109 ; ok ------------------+
0114: F8 MOV A,R0 ; TEST 1KB ROM ----------+
0115: A3 MOVP A,@A ; read Page-1 |
0116: 14 E5 CALL $00E5 ; sum |
0118: E3 MOVP3 A,@A ; read Page-3 |
0119: 14 E5 CALL $00E5 ; sum |
011B: 14 E4 CALL $00E4 ; read Page-0 and sum |
011D: 54 00 CALL $0200 ; read Page-2 and sum |
011F: E8 14 DJNZ R0,$0114 ; -----------------------+
0121: F9 MOV A,R1
0122: 96 28 JNZ $0128 ; sum non-zero? -> err
0124: 23 AA MOV A,#$AA ;
0126: 54 20 CALL $0220 ; --> OK sum=0: Put AA into FIFO (will send Self-test passed), then Start
0128: 04 10 JMP $0010 ; --> RAM err, ROM chksum err: just Start
012A: | 00 00 00 00 00 00 | ................
0130: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
0140: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
0150: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
0160: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
0170: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
0180: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
0190: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
01A0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
01B0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
01C0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
01D0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
01E0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
01F0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
>> SUB TEST ROM chksum
0200: A3 MOVP A,@A ; read page-2
0201: 04 E5 JMP $00E5 ; add and return
*************************************
** SUB SHIFT FIFO after transmit **
*************************************
0203: D5 SEL RB1
0204: F8 MOV A,R0
0205: 07 DEC A ; dec FIFO PTR $18
0206: AF MOV R7,A ; last byte to move
0207: A8 MOV R0,A
0208: D3 20 XRL A,#$20 : nothing to move?
020A: 96 0E JNZ $020E
020C: A5 CLR F1 ; set FIFO empty and RETR
020D: 93 RETR
020E: B9 21 MOV R1,#$21 ; at least one more above $20
0210: F1 MOV A,@R1 ; ---------------------------+
0211: C9 DEC R1 |
0212: A1 MOV @R1,A |
0213: 19 INC R1 |
0214: FF MOV A,R7 |
0215: D9 XRL A,R1 |
0216: C6 0D JZ $020D ; last moved? -> RETR |
0218: F9 MOV A,R1 ; (redundant.. |
0219: D3 30 XRL A,#$30 ; never executes?) |
021B: C6 0D JZ $020D ; moved last as $30? -> RETR |
021D: 19 INC R1 ; next |
021E: 44 10 JMP $0210 ; ---------------------------+
R7 R7 would be anyway
| |
$20 $21 $22 $23 $24 .. .. .. .. .. .. .. .. .. .. $30
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| <-- <-- <-- FF Scancode FIFO
$18 -----------------------------------´ shift FIFO |
FIFO PTR FIFO empty: $18=20 and F1=0 overrun byte
next slot to fill
*********************************
** SUB Put 'A' into FIFO **
*********************************
0220: D5 SEL RB1
0221: 76 26 JF1 $0226
0223: B8 20 MOV R0,#$20 ; F1=0, FIFO empty: init FIFO PTR $18=20
0225: B5 CPL F1 ; and set F1=1 (FIFO has data)
0226: AF MOV R7,A ; save A
0227: F8 MOV A,R0
0228: D3 31 XRL A,#$31
022A: C6 34 JZ $0234 ; $18=31? -> FIFO full: RETR
022C: 07 DEC A
022D: 96 31 JNZ $0231
022F: BF FF MOV R7,#$FF ; last slot to fill, $18=30: load FIFO overrun byte
0231: FF MOV A,R7 ; ok, restore A
0232: A0 MOV @R0,A ; store at @$18
0233: 18 INC R0 ; inc FIFO PTR
0234: 93 RETR
*********************************
** SUB Send A **
*********************************
IRQ1: when set (pending, serviced) it also pulls DATA low on the system board -> before sending anything, 8048 releases DATA.. and checks if stays high.
If it's low, polls it for a while and waits for PC to finish processing the previous byte.
XT KBD_RESET:
BIOS holds CLK low for 20ms.. then reads port. When 'AA' it is a keyboard.
When '65' then there is a test-board connected thru the KB DIN: loads a test program to 500h and executes. This is MANUFACTURING TEST 2.
0235: D5 SEL RB1 ; Select Register Bank 1
0236: 85 CLR F0
0237: 95 CPL F0 ; F0=1
0238: 26 87 JNT0 $0287 ; CLK held low? REQIN ->
023A: 76 3D JF1 $023D ; F1 set? scancode in FIFO? -> send
023C: 93 RETR ; SEL RB0
023D: B9 20 MOV R1,#$20 ; F1 set:
023F: F1 MOV A,@R1 ; load from FIFO $20
0240: 97 CLR C
0241: A7 CPL C ; set Carry (prepare sending 9 bits starting with '1')
0242: F7 RLC A ; rotate thru carry = 7 6 5 4 3 2 1 0 C
0243: 26 87 JNT0 $0287 ; CLK went low in the meantime? do REQIN instead ->
0245: 98 BF ANL BUS,#$BF ; ok, CLK high: pull it low
0247: 88 20 ORL BUS,#$20 ; and release DATA..
0249: 00 NOP
024A: 00 NOP ; = KB signals a REQOUT:
024B: BF 0E MOV R7,#$0E ; now check if DATA stays high (when low, wait a little, probably IRQ1 pending and DATA pulled low by PC)
024D: 86 53 JNI $0253 ; --------------+
024F: 86 55 JNI $0255 |
0251: 44 5C JMP $025C ; -> DATA released, high -> transmit
0253: 44 55 JMP $0255 |
0255: EF 4D DJNZ R7,$024D ; --------------+
0257: 88 40 ORL BUS,#$40 ; DATA still low: we give up, release CLK high
0259: 98 DF ANL BUS,#$DF ; pull DATA low (KB idle state)
025B: 93 RETR ; and RETR
************************************
** JMP DATA low: transmit A **
************************************
________
C \_______ We enter here with a stable REQOUT state: 8048 pulls CLK low and DATA is released.
_______ Carry and A has the 'pre-rotated' 9-bits to transmit: x x x x x x x x 1 -> KB DATA
D________/ Transmission is lsb first when CLK is low. LS322 latches data on the low-to-high clock transition.
During normal operation the LS322 is cleared and enabled. IRQ1 is cleared: the IRQ flip-flop is in RESET state. The KB will send 9 bits of data: START=1 and 8 data bits. Bits 'rotated right' into LS322 (note the flip-flops' output A..H from the LS322 are connected 'backwards' to PORT-A). When START=1 reaches FF-H/bit0, QH' goes high. Although QH' is connected to the D input of the IRQ-FF, there is a propagation delay - that time IRQ-FF has already latched the 'previous' state of QH', i.e. still low. When the last bit arrives IRQ-FF enters its PRESET state and IRQ1 is signalled. Also, Q* goes low and does two things. It keeps KB DATA pulled low: the KB will not send another byte until KB DATA is released again. Q* is also connected back to PRE*: it 'locks' the FF in the PRESET-STATE regardless of what's happenning from now on on the D input. It can only be RESET again by asserting CLR*, which is connected to PB7 and driven by the ISR, i.e. interrupt has been served. Then the IRQ flip-flop is in RESET state again.
LS322 IRQ-FF
+---------------------------------------+ +----------+
| | delay | | Q --------------> IRQ1
KB DATA ---> D | -> FF-A -> FF-B ... -> FF-H --| QH' ---------------> D | |
____CLK | | | | | ___ CLK | ___ ___ | Q* ---+--- - - -> KB DATA
__/ | | | | | __/ | CLR PRE | |
+---------------------------------------+ +----------+ |
| | | | +----------+
PA7 PA6 ... PA0 PB7
.
This works, because: CLK goes high in the same time for LS322 and IRQ-FF. QH' appears after ~22ns (typ propagation delay). IRQ-FF need only a 5ns hold time for the input, so it will sample the previous state of QH'!
025C: BF 09 MOV R7,#$09
025E: 00 NOP
025F: EF 5F DJNZ R7,$025F ; delay..
0261: BF 09 MOV R7,#$09 ; start rotating out 9 bits, lsb first (starting with '1' then 8-bit data)
0263: BE 0A MOV R6,#$0A ; load delay -------------------------+
0265: 12 6D JB0 $026D ; |
0267: 98 DF ANL BUS,#$DF ; bit='0': pull DATA low |
0269: 88 40 ORL BUS,#$40 ; set CLK high |
026B: 44 73 JMP $0273 |
026D: 88 20 ORL BUS,#$20 ; bit='1': set DATA high |
026F: 88 40 ORL BUS,#$40 ; set CLK high |
0271: 44 73 JMP $0273 |
0273: EE 73 DJNZ R6,$0273 ; delay.. |
0275: 00 NOP ; let LS322 latch it in |
0276: 98 BF ANL BUS,#$BF ; pull CLK low |
0278: 67 RRC A |
0279: EF 63 DJNZ R7,$0263 ; ------------------------------------+
________ | __ | __ | __ | | __ | ________|
C \_______|____/ \_|____/ \_|____/ \_| |____/ \_|____/ | done
_______|__ ______|__ ______|__ ______| .... |__ ______|__ | bus idle
D________/ | 1 | X______|__X______| |__X______| \__________|
| | | | | ^ | |
CY 0 1 7 |
|
START=1 |
REQOUT 1. write DATA LS322 STOP
state 2. set CLK high latches
3. delay on rising
4. pull CLK low edge
027B: 98 DF ANL BUS,#$DF ; STOP: pull DATA low
027D: 00 NOP
027E: 00 NOP
027F: 00 NOP
0280: 00 NOP
0281: 00 NOP
0282: 88 40 ORL BUS,#$40 ; release CLK high
0284: 54 03 CALL $0203 ; Shift FIFO
0286: 93 RETR
****************************************
** JNT0 REQIN: CLK held low by PC **
****************************************
In the BIOS RESET_KBD routine
0287: BF 08 MOV R7,#$08
0289: EF 89 DJNZ R7,$0289 ; delay
028B: 36 86 JT0 $0286 ; CLK went high in the meantime? -> RETR
028D: 98 BF ANL BUS,#$BF ; we also pull CLK low
028F: 88 20 ORL BUS,#$20 ; and release DATA, high
0291: BF 11 MOV R7,#$11
0293: EF 93 DJNZ R7,$0293 ; delay.. (make sure BIOS releases CLK? we'll drive it from now on)
________ | __ | __ | | __ | ________|
C \_______|__/ \_____|__/ \_____| |__/ \_____|____/ | done
_______|___________|___________| ...... |___________|__ | bus idle
D________/ | | | | | \__________|
| ^ ^ | ^ ^ | | ^ ^ | |
| | | | | |
sample sample sample
DATA DATA DATA
R6=9 R6=8 R6=1
Before BIOS wants to reset the KB by pulling CLK low for a long time (clearing PB6), it first disables the LS322 (clearing PB7). This also releases
(20ms), it first disables the LS322. This puts all its outputs to HIGH-Z. Because of the pull-up the DATA line is therefore high, and this code checks it: reads 9 bits from DATA and accepts the RESET only when all bits read are '1'. It samples all bits twice and signals any difference by clearing F0, but this is not checked afterwards(?).
0295: BE 09 MOV R6,#$09 ; read 9-bits from DATA: PC BIOS is suppose to disable LS322 before this. We should sample only '1's
0297: 88 40 ORL BUS,#$40 ; set CLK high----------+
0299: BF 08 MOV R7,#$08 |
029B: EF 9B DJNZ R7,$029B ; delay.. |
029D: 98 BF ANL BUS,#$BF ; pull CLK low |
029F: 86 AA JNI $02AA ; DATA low? -> |
02A1: 43 01 ORL A,#$01 ; H: rotate '1' into A |
02A3: 86 AE JNI $02AE ; flipped? err -> |
02A5: 67 RRC A ; OK: rotate |
02A6: EE 97 DJNZ R6,$0297 ; ---- 9 times ---------+
02A8: 44 B1 JMP $02B1 ; -> exit |
02AA: 53 FE ANL A,#$FE ; rotate '0' into A |
02AC: 86 A5 JNI $02A5 ; still low? ok |
02AE: 85 CLR F0 ; no, flipped? err | <- clear F0 but not checked afterwards..?
02AF: 44 A5 JMP $02A5 ; ----------------------+
02B1: 88 40 ORL BUS,#$40 ; set CLK high, release
02B3: BF 05 MOV R7,#$05
02B5: EF B5 DJNZ R7,$02B5 ; delay..
02B7: 98 DF ANL BUS,#$DF ; pull DATA low (bus idle state)
02B9: 37 CPL A
02BA: 96 86 JNZ $0286 ; -> got any bits pulled low? just RETR
02BC: E6 86 JNC $0286 ; -> 9th bit Carry zero? just RETR
02BE: 24 00 JMP $0100 ; -> OK: received only '1' bits: proper KBD_RESET, run BAT and go to Start
02C0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
02D0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
02E0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
02F0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
*******************************************
** SCANCODE TABLE **
** **
** For the 12 x 8 = 96 key matrix **
*******************************************
0300: 00 4e 51 4d 4a 49 00 46 | 53 50 4f 4c 4b 47 48 45 | .NQMJI.FSPOLKGHE
0310: 52 37 36 29 1c 00 00 0e | 3a 35 28 00 1b 1a 00 0d | R76)....:5(.....
0320: 00 34 27 26 00 19 0c 0b | 32 33 25 24 18 17 0a 09 | .4'&....23%$....
0330: 39 31 30 23 16 15 08 07 | 2e 2f 22 21 14 13 06 05 | 910#...../"!....
0340: 2d 2c 20 1f 12 11 04 03 | 2b 2a 1d 1e 10 0f 02 01 | -, .....+*......
0350: 38 44 42 40 00 3e 00 3c | 00 43 41 3f 00 3d 76 3b | 8DB@.>.<.CA?.=v;
|
76? For ROM chksum?
Why here, there are plenty of 00-s in the ROM to use..
*******************************************
** Typematic counter **
** Delay or Rate in R3 **
*******************************************
Main Loop signals beginning of scan by clearing $1B.
This routine checks $1B and if zero, sets it to 01 and
decrements the $1A counter to count the (fix) Typematic Delay or Rate.
>> SUB called when a key depressed for the first time
0360: D5 SEL RB1
0361: BA 26 MOV R2,#$26 ; $1A = 26 (FIX typematic delay: 38 full scan)
>> SUB called when a key is still held between scans
0363: D5 SEL RB1
0364: FB MOV A,R3
0365: 12 76 JB0 $0376 ; $1B_0 set? --> RETR
0367: 43 01 ORL A,#$01
0369: AB MOV R3,A ; not set: set it
036A: CA DEC R2 ; dec $1A
036B: FA MOV A,R2
036C: 96 76 JNZ $0376 ; non-zero? --> RETR
036E: BA 06 MOV R2,#$06 ; $1A is zero: set $1A = 06 (FIX typematic rate: 6 full scan)
0370: C5 SEL RB0
0371: FD MOV A,R5 ; R5 typematic
0372: C6 76 JZ $0376
0374: 54 20 CALL $0220 ; R5 typematic nonzero: --> Put 'A' into FIFO
0376: 93 RETR
0377: 00 | 00 00 00 00 00 00 00 00 | ................
0380: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
0390: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
03A0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
03B0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
03C0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
03D0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
03E0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................
03F0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | ................