source: trunk/I8253.pas

Last change on this file was 8, checked in by chronos, 3 weeks ago
  • Modified: Implemented more instructions.
  • Added: Hardware emulation of 8255 and 8253 chips.
File size: 3.3 KB
Line 
1unit I8253;
2
3interface
4
5uses
6 Classes, SysUtils;
7
8type
9 TCounterMode = 0..5;
10 TReadLoad = (rlCounterLatching, rlMostByteOnly,
11 rlLeastByteOnly, rlLeastThenMostByte);
12 TByteKind = (bkLeast, bkMost);
13 TOutputEvent = procedure (Output: Boolean) of object;
14
15 { TCounter }
16
17 TCounter = record
18 private
19 FOnOutputChange: TOutputEvent;
20 public
21 ResetValue: Word;
22 Value: Word;
23 Mode: TCounterMode;
24 Bcd: Boolean;
25 ReadLoad: TReadLoad;
26 ReadLoadByteKind: TByteKind;
27 StorageValue: Word;
28 procedure Load(Data: Byte);
29 function Read: Byte;
30 procedure Control(Data: Byte);
31 procedure CountDown;
32 property OnOutputChange: TOutputEvent read FOnOutputChange
33 write FOnOutputChange;
34 end;
35
36 { T8253 }
37
38 T8253 = class
39 Counters: array[0..2] of TCounter;
40 procedure Write(Address: Word; Data: Byte);
41 function Read(Address: Word): Byte;
42 constructor Create;
43 end;
44
45
46implementation
47
48{ TCounter }
49
50procedure TCounter.Load(Data: Byte);
51begin
52 case ReadLoad of
53 rlCounterLatching: ;
54 rlLeastByteOnly: Value := (ResetValue and $ff00) or Data;
55 rlMostByteOnly: Value := (ResetValue and $ff) or (Data shl 8);
56 rlLeastThenMostByte: begin
57 case ReadLoadByteKind of
58 bkLeast: begin
59 Value := (Value and $ff00) or Data;
60 ReadLoadByteKind := bkMost;
61 end;
62 bkMost: begin
63 Value := (Value and $ff) or (Data shl 8);
64 ReadLoadByteKind := bkLeast;
65 end;
66 end;
67 end;
68 end;
69end;
70
71function TCounter.Read: Byte;
72begin
73 case ReadLoad of
74 rlCounterLatching: begin
75 case ReadLoadByteKind of
76 bkLeast: begin
77 Result := StorageValue and $ff;
78 ReadLoadByteKind := bkMost;
79 end;
80 bkMost: begin
81 Result := (StorageValue shr 8) and $ff;
82 ReadLoadByteKind := bkLeast;
83 end;
84 end;
85 end;
86 else begin
87 case ReadLoadByteKind of
88 bkLeast: begin
89 Result := Value and $ff;
90 ReadLoadByteKind := bkMost;
91 end;
92 bkMost: begin
93 Result := (Value shr 8) and $ff;
94 ReadLoadByteKind := bkLeast;
95 end;
96 end;
97 end;
98 end;
99end;
100
101procedure TCounter.Control(Data: Byte);
102begin
103 ReadLoad := TReadLoad((Data and $30) shr 4);
104 case ReadLoad of
105 rlCounterLatching: StorageValue := Value;
106 rlMostByteOnly: ReadLoadByteKind := bkMost;
107 rlLeastByteOnly: ReadLoadByteKind := bkLeast;
108 rlLeastThenMostByte: ReadLoadByteKind := bkLeast;
109 end;
110 Mode := (Data and $e) shr 1;
111 Bcd := (Data and 1) > 0;
112end;
113
114procedure TCounter.CountDown;
115begin
116 if Value > 0 then begin
117 Dec(Value);
118 if Value = 0 then begin
119 if Assigned(FOnOutputChange) then
120 FOnOutputChange(True);
121 end;
122 end;
123end;
124
125{ T8253 }
126
127procedure T8253.Write(Address: Word; Data: Byte);
128var
129 CounterNum: Byte;
130begin
131 case Address of
132 0: Counters[0].Load(Data);
133 1: Counters[1].Load(Data);
134 2: Counters[2].Load(Data);
135 3: begin
136 CounterNum := (Data and $c0) shr 6;
137 Counters[CounterNum].Control(Data);
138 end;
139 end;
140end;
141
142function T8253.Read(Address: Word): Byte;
143begin
144 case Address of
145 0: Result := Counters[0].Read;
146 1: Result := Counters[1].Read;
147 2: Result := Counters[2].Read;
148 3: Result := 0; // Illegal
149 end;
150end;
151
152constructor T8253.Create;
153var
154 I: Integer;
155begin
156 for I := 0 to 2 do
157 Counters[I].Value := 0;
158end;
159
160end.
161
Note: See TracBrowser for help on using the repository browser.