DOS ortamında, PC printer portundaki 5 giriş pini (10,11,12,13,15 numaralı pinler) kullanarak, PC klavyesindeki tuşları emule edebilecek, 16 tuşlu bir klavye nasıl yapılabilir? Aşağıda bahsedeceğim sistem bu soruya cevap vermek için yapıldı. Kullanım alanı epey geniş olmasına rağmen hiç bir sistemde kullanılamadı ama DOS ve PC hardware programlama konusunda iyi bir örnek olduğunu düşünüyorum.
Bu sistemi DOS ortamında çalışacak şekilde yaptım. Çünkü 1996 yılında Windows programcısı değildim. PC printer portunu kullandım çünkü bu şekilde çok az elektronik komponent kullanılarak sonuç alınabiliyor. PC klavyesini emule edecek bir sistem tasarladım çünkü bu klavye olmadan da uygulamaların çalısmasını test edebilmek istedim.
Sistem şu şekilde çalışıyor:
Bir 27512 epromu 16'dan 4'e çözücü olarak kullanıyoruz. Epromun address bus'ı tuş takımına ve data bus'ının 4 bitide printer porta bağlanıyor. Epromun data bitlerinden birinide printer portun IRQ ucu olan 10 numaralı pine bağlıyoruz ki tuşa her basıldığında oluşan IRQ ile PC klavye buffer'ına karakter kodlarını yazabilelim. Aşağıdaki tabloyu kullanarak epromun 16 adresini programlıyoruz.
Pin Desc Address Data(Binary) Data(Decimal) Key --------------------------------------------------------------- 10 A0 1 00010000 16+0 '1' 9 A1 2 00010001 16+1 '2' 8 A2 4 00010010 16+2 '3' 7 A3 8 00010011 16+3 (F1) 6 A4 16 00010100 16+4 '4' 5 A5 32 00010101 16+5 '5' 4 A6 64 00010110 16+6 '6' 3 A7 128 00010111 16+7 (Yukarı) 25 A8 256 00011000 16+8 '7' 24 A9 512 00011001 16+9 '8' 21 A10 1024 00011010 16+10 '9' 23 A11 2048 00011011 16+11 (Aşağı) 2 A12 4096 00011100 16+12 #32 (Space) 26 A13 8192 00011101 16+13 '0' 27 A14 16384 00011110 16+14 #13 (Enter) 1 A15 32768 00011111 16+15 #27 (Esc)
Diger adreslere de 0 yazdığımız zaman epromun programlanması işi bitiyor. Eproma yazılacak dosyayı üreten kod:
------------------- BEGIN EPROM FILE GENERATOR CODE --------------------
{$A-,B-,D-,E-,F-,G-,I+,L-,N-,O-,P-,Q-,R-,S-,T-,V-,X-}
{$M 16384,0,655360}
{ Eprom file generator for 16Key }
const
FName : string = '27512.Dat';
var
F : file;
I : byte;
Buf : array[1..2048] of byte;
A : byte;
begin
FillChar(Buf,SizeOf(Buf),#0);
Assign(F,FName);
{$I-}
ReWrite(F,1);
for I := 1 to 32 do BlockWrite(F,Buf,SizeOf(Buf));
A := 0 + 16;
Seek(F,65535 - 1);
BlockWrite(F,A,SizeOf(A));
A := 1 + 16;
Seek(F,65535 - 2);
BlockWrite(F,A,SizeOf(A));
A := 2 + 16;
Seek(F,65535 - 4);
BlockWrite(F,A,SizeOf(A));
A := 3 + 16;
Seek(F,65535 - 8);
BlockWrite(F,A,SizeOf(A));
A := 4 + 16;
Seek(F,65535 - 16);
BlockWrite(F,A,SizeOf(A));
A := 5 + 16;
Seek(F,65535 - 32);
BlockWrite(F,A,SizeOf(A));
A := 6 + 16;
Seek(F,65535 - 64);
BlockWrite(F,A,SizeOf(A));
A := 7 + 16;
Seek(F,65535 - 128);
BlockWrite(F,A,SizeOf(A));
A := 8 + 16;
Seek(F,65535 - 256);
BlockWrite(F,A,SizeOf(A));
A := 9 + 16;
Seek(F,65535 - 512);
BlockWrite(F,A,SizeOf(A));
A := 10 + 16;
Seek(F,65535 - 1024);
BlockWrite(F,A,SizeOf(A));
A := 11 + 16;
Seek(F,65535 - 2048);
BlockWrite(F,A,SizeOf(A));
A := 12 + 16;
Seek(F,65535 - 4096);
BlockWrite(F,A,SizeOf(A));
A := 13 + 16;
Seek(F,65535 - 8192);
BlockWrite(F,A,SizeOf(A));
A := 14 + 16;
Seek(F,65535 - 16384);
BlockWrite(F,A,SizeOf(A));
A := 15 + 16;
Seek(F,65535 - 32768);
BlockWrite(F,A,SizeOf(A));
Close(F);
end.
--------------------- END EPROM FILE GENERATOR CODE -------------------
DOS ortamında bu sistemi çalıştırmak için bir TSR program olması gerekiyor. Bu kod aşağıda.
------------------------ BEGIN DRIVER CODE -----------------------------
{$A-,B-,D-,E-,F-,G-,I-,L-,N-,O-,P-,Q-,R-,S-,T-,V-,X-}
{$M 1024,0,0}
program 16KDrv;
uses Crt,Dos;
var
OldInt : procedure;
BaseAdr : word absolute $0000:$0408;
function ReadKB(var Key:byte):boolean;
var
A : byte;
begin
Key := 0;
A := Port[BaseAdr + 1];
if (A and 32) <> 0 then Key := Key or 1;
if (A and 16) <> 0 then Key := Key or 2;
if (A and 8) <> 0 then Key := Key or 4;
if (A and 128) = 0 then Key := Key or 8;
ReadKB := (A and 64) <> 0;
end;
(*
{ Direct access to KeyBoard Buffer }
procedure Write2KBuf(C: char);
var
KBuffer : array[0..15] of word absolute $0000:$041E;
Tail : word absolute $0000:$041C;
Head : word absolute $0000:$041A;
begin
if Tail + 2 = Head then
begin
Sound(1000);
Delay(100);
NoSound;
Exit;
end;
KBuffer[(Tail div 2) - 15] := byte(C);
Inc(Tail,2);
if Tail > 60 then Tail := 30;
end;
*)
procedure Beep;
begin
Sound(1000);
Delay(100);
NoSound;
end;
procedure Write2KBuf(W: word);assembler;
asm
mov ah,05h
mov cx,W
int 16h
and al,al
jz @Quit
call Beep
@Quit:
end;
{$F+}
procedure NewInt;interrupt;
const
CTable : array[0..15] of word =
(48 + 1 + 256 * 2,
48 + 2 + 256 * 3,
48 + 3 + 256 * 4,
8 + 256 * 14,
48 + 4 + 256 * 5,
48 + 5 + 256 * 6,
48 + 6 + 256 * 7,
0 + 256 * 72,
48 + 7 + 256 * 8,
48 + 8 + 256 * 9,
48 + 9 + 256 * 10,
0 + 256 * 80,
32 + 256 * 57,
48 + 0 + 256 * 11,
27 + 256 * 1,
13 + 256 * 28);
var
Key : byte;
begin
InLine($FB); { Sti }
Delay(20);
if ReadKB(Key) then Write2KBuf(CTable[Key]);
InLine($FA); { Cli }
Port[$20] := $20; { Reset the 8259 PIC }
asm
PushF
Call OldInt
end;
end;
{$F-}
begin
ClrScr;
Port[BaseAdr + 2] := Port[BaseAdr + 2] or 16; (Enable PRN IRQ)
Port[$21] := $00;
Port[$20] := $20; (Unmask IRQ #7)
GetIntVec($0F,@OldInt);
SetIntVec($0F,@NewInt);
Keep(0);
end.
---------------------------- END DRIVER CODE----------------------------
Bu klavyeyi likit kristal ekranla beraber kullanma şansımız var. Çünkü printer portun sadece 5 giriş pinini kullandık. Likit kristal ekransa 8 data biti ve 2 kontrol biti daha gerektiriyor ki zaten printer portta bu kadar boş yer var. İki sistem bir arada kullanıldığında geriye bilgisayarın geriye sadece kasası kalıyor.
Yazılım olarak en büyük eksiği sadece DOS ortamında çalışıyor olması. Eğer sürücü TSR yerine bir vxd yazılırsa Windows ortamında da çalışması mümkün ama bunu yapmak için kullanılacağı bir yer bulmak şart.