Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | daniel-mar | 1 | unit HT46F47; |
2 | |||
3 | interface |
||
4 | |||
5 | type |
||
6 | Nibble = 0..15; |
||
7 | |||
8 | TRom = array[0..$FF] of byte; |
||
9 | |||
3 | daniel-mar | 10 | TWaitEvent = procedure(milliseconds: integer) of object; |
11 | |||
2 | daniel-mar | 12 | THT46F47 = class(TObject) |
13 | strict private |
||
14 | procedure WaitMs(milliseconds: integer); |
||
15 | strict protected |
||
3 | daniel-mar | 16 | FOnWait: TWaitEvent; |
2 | daniel-mar | 17 | // ROM |
18 | // Registers |
||
19 | FPC: byte; |
||
20 | FReturnAddress: byte; |
||
21 | FPage: Nibble; |
||
22 | FRegA: Nibble; |
||
23 | FRegB: Nibble; |
||
24 | FRegC: Nibble; |
||
25 | FRegD: Nibble; |
||
26 | FCalledOnce: boolean; |
||
27 | // In |
||
28 | FS1: boolean; |
||
29 | FS2: boolean; |
||
30 | FDIn: Nibble; |
||
31 | FAD1: Nibble; |
||
32 | FAD2: Nibble; |
||
33 | // Out |
||
34 | FPWM: Nibble; |
||
35 | FPortOut: Nibble; |
||
36 | public |
||
37 | // ROM |
||
38 | ROM: TRom; |
||
39 | property FROM: TRom read ROM; |
||
40 | // Registers |
||
41 | property PC: byte read FPC; |
||
42 | property ReturnAddress: byte read FReturnAddress; |
||
43 | property Page: Nibble read FPage; |
||
44 | property RegA: Nibble read FRegA; |
||
45 | property RegB: Nibble read FRegB; |
||
46 | property RegC: Nibble read FRegC; |
||
47 | property RegD: Nibble read FRegD; |
||
48 | // In |
||
49 | property S1: boolean read FS1 write FS1; |
||
50 | property S2: boolean read FS2 write FS2; |
||
51 | property DIn: Nibble read FDIn write FDIn; |
||
52 | property AD1: Nibble read FAD1 write FAD1; |
||
53 | property AD2: Nibble read FAD2 write FAD2; |
||
54 | // Out |
||
55 | property PWM: Nibble read FPWM; |
||
56 | property PortOut: Nibble read FPortOut; |
||
57 | // Functions |
||
3 | daniel-mar | 58 | property OnWait: TWaitEvent read FOnWait write FOnWait; |
2 | daniel-mar | 59 | constructor Create; |
60 | procedure Step; |
||
61 | procedure Reset; |
||
62 | end; |
||
63 | |||
64 | implementation |
||
65 | |||
66 | uses |
||
67 | SysUtils, Forms; |
||
68 | |||
69 | { THT46F47 } |
||
70 | |||
71 | constructor THT46F47.Create; |
||
72 | var |
||
73 | i: integer; |
||
74 | begin |
||
75 | for i := Low(FROM) to High(FROM) do |
||
76 | begin |
||
77 | ROM[i] := $00; |
||
78 | end; |
||
79 | Reset; |
||
80 | end; |
||
81 | |||
82 | procedure THT46F47.Reset; |
||
83 | begin |
||
84 | // Internal |
||
85 | FPC := 0; |
||
86 | FReturnAddress := 0; |
||
87 | FPage := 0; |
||
88 | FRegA := 0; // Note: The registers don't seem to be reset in the actual chip, if a "soft reset" is done |
||
89 | FRegB := 0; |
||
90 | FRegC := 0; |
||
91 | FRegD := 0; |
||
92 | FCalledOnce := false; |
||
93 | // In |
||
94 | FS1 := false; |
||
95 | FS2 := false; |
||
96 | FDIn := 0; |
||
97 | FAD1 := 0; |
||
98 | FAD2 := 0; |
||
99 | // Out |
||
100 | FPWM := 0; |
||
101 | FPortOut := 0; |
||
102 | end; |
||
103 | |||
104 | procedure THT46F47.Step; |
||
105 | var |
||
106 | Instruction: byte; |
||
107 | ProgramCounterNext: Byte; |
||
108 | ProgramCounterCurrent: Byte; |
||
109 | begin |
||
110 | Instruction := FROM[FPC]; |
||
111 | |||
112 | ProgramCounterCurrent := FPC; |
||
113 | ProgramCounterNext := FPC+1; |
||
114 | |||
115 | try |
||
116 | (* |
||
117 | ---------------------------------------------------- |
||
118 | Code Assembly Alternative Comment |
||
119 | ---------------------------------------------------- |
||
120 | 10 LED 0000 PORT 0 |
||
121 | 11 LED 0001 PORT 1 |
||
122 | 12 LED 0010 PORT 2 |
||
123 | 13 LED 0011 PORT 3 |
||
124 | 14 LED 0100 PORT 4 |
||
125 | 15 LED 0101 PORT 5 |
||
126 | 16 LED 0110 PORT 6 |
||
127 | 17 LED 0111 PORT 7 |
||
128 | 18 LED 1000 PORT 8 |
||
129 | 19 LED 1001 PORT 9 |
||
130 | 1A LED 1010 PORT 10 |
||
131 | 1B LED 1011 PORT 11 |
||
132 | 1C LED 1100 PORT 12 |
||
133 | 1D LED 1101 PORT 13 |
||
134 | 1E LED 1110 PORT 14 |
||
135 | 1F LED 1111 PORT 15 |
||
136 | *) |
||
137 | if (Instruction >= $10) and (Instruction <= $1F) then |
||
138 | begin |
||
139 | FPortOut := Instruction and $F; |
||
140 | end; |
||
141 | |||
142 | (* |
||
143 | ---------------------------------------------------- |
||
144 | Code Assembly Alternative Comment |
||
145 | ---------------------------------------------------- |
||
146 | 20 WAIT 1ms |
||
147 | 21 WAIT 2ms |
||
148 | 22 WAIT 5ms |
||
149 | 23 WAIT 10ms |
||
150 | 24 WAIT 20ms |
||
151 | 25 WAIT 50ms |
||
152 | 26 WAIT 100ms |
||
153 | 27 WAIT 200ms |
||
154 | 28 WAIT 500ms |
||
155 | 29 WAIT 1s |
||
156 | 2A WAIT 2s |
||
157 | 2B WAIT 5s |
||
158 | 2C WAIT 10s |
||
159 | 2D WAIT 20s |
||
160 | 2E WAIT 30s |
||
161 | 2F WAIT 60s |
||
162 | *) |
||
163 | case Instruction of |
||
164 | $20: WaitMs(1); // WAIT 1ms |
||
165 | $21: WaitMs(2); // WAIT 2ms |
||
166 | $22: WaitMs(5); // WAIT 5ms |
||
167 | $23: WaitMs(10); // WAIT 10ms |
||
168 | $24: WaitMs(20); // WAIT 20ms |
||
169 | $25: WaitMs(50); // WAIT 50ms |
||
170 | $26: WaitMs(100); // WAIT 100ms |
||
171 | $27: WaitMs(200); // WAIT 200ms |
||
172 | $28: WaitMs(500); // WAIT 500ms |
||
173 | $29: WaitMs(1000); // WAIT 1s |
||
174 | $2A: WaitMs(2000); // WAIT 2s |
||
175 | $2B: WaitMs(5000); // WAIT 5s |
||
176 | $2C: WaitMs(10000); // WAIT 10s |
||
177 | $2D: WaitMs(20000); // WAIT 20s |
||
178 | $2E: WaitMs(30000); // WAIT 30s |
||
179 | $2F: WaitMs(60000); // WAIT 60s |
||
180 | end; |
||
181 | |||
182 | (* |
||
183 | ---------------------------------------------------- |
||
184 | Code Assembly Alternative Comment |
||
185 | ---------------------------------------------------- |
||
186 | 30 JUMP -0 HALT |
||
187 | 31 JUMP -1 |
||
188 | 32 JUMP -2 |
||
189 | 33 JUMP -3 |
||
190 | 34 JUMP -4 |
||
191 | 35 JUMP -5 |
||
192 | 36 JUMP -6 |
||
193 | 37 JUMP -7 |
||
194 | 38 JUMP -8 |
||
195 | 39 JUMP -9 |
||
196 | 3A JUMP -10 |
||
197 | 3B JUMP -11 |
||
198 | 3C JUMP -12 |
||
199 | 3D JUMP -13 |
||
200 | 3E JUMP -14 |
||
201 | 3F JUMP -15 |
||
202 | *) |
||
203 | if (Instruction >= $30) and (Instruction <= $3F) then |
||
204 | begin |
||
205 | ProgramCounterNext := ProgramCounterCurrent - (Instruction and $F); |
||
206 | end; |
||
207 | |||
208 | (* |
||
209 | ---------------------------------------------------- |
||
210 | Code Assembly Alternative Comment |
||
211 | ---------------------------------------------------- |
||
212 | 40 SET A=0 |
||
213 | 41 SET A=1 |
||
214 | 42 SET A=2 |
||
215 | 43 SET A=3 |
||
216 | 44 SET A=4 |
||
217 | 45 SET A=5 |
||
218 | 46 SET A=6 |
||
219 | 47 SET A=7 |
||
220 | 48 SET A=8 |
||
221 | 49 SET A=9 |
||
222 | 4A SET A=10 |
||
223 | 4B SET A=11 |
||
224 | 4C SET A=12 |
||
225 | 4D SET A=13 |
||
226 | 4E SET A=14 |
||
227 | 4F SET A=15 |
||
228 | *) |
||
229 | if (Instruction >= $40) and (Instruction <= $4F) then |
||
230 | begin |
||
231 | FRegA := Instruction and $F; |
||
232 | end; |
||
233 | |||
234 | (* |
||
235 | ---------------------------------------------------- |
||
236 | Code Assembly Alternative Comment |
||
237 | ---------------------------------------------------- |
||
238 | 50 |
||
239 | 51 SET B=A |
||
240 | 52 SET C=A |
||
241 | 53 SET D=A |
||
242 | 54 SET Dout=A |
||
243 | 55 SET Dout.0=A.0 |
||
244 | 56 SET Dout.1=A.0 |
||
245 | 57 SET Dout.2=A.0 |
||
246 | 58 SET Dout.3=A.0 |
||
247 | 59 SET PWM=A |
||
248 | 5A |
||
249 | 5B |
||
250 | 5C |
||
251 | 5D |
||
252 | 5E |
||
253 | 5F |
||
254 | *) |
||
255 | case Instruction of |
||
256 | $51: FRegB := FRegA; // SET B=A |
||
257 | $52: FRegC := FRegA; // SET C=A |
||
258 | $53: FRegD := FRegA; // SET D=A |
||
259 | $54: FPortOut := FRegA; // SET Dout=A |
||
260 | $55: FPortOut := ((FRegA and 1) shl 0) + (PortOut and 14); // SET Dout.0=A.0 |
||
261 | $56: FPortOut := ((FRegA and 1) shl 1) + (PortOut and 13); // SET Dout.1=A.0 |
||
262 | $57: FPortOut := ((FRegA and 1) shl 2) + (PortOut and 11); // SET Dout.2=A.0 |
||
263 | $58: FPortOut := ((FRegA and 1) shl 3) + (PortOut and 7); // SET Dout.3=A.0 |
||
264 | $59: FPWM := FRegA; // SET PWM=A |
||
265 | end; |
||
266 | |||
267 | (* |
||
268 | ---------------------------------------------------- |
||
269 | Code Assembly Alternative Comment |
||
270 | ---------------------------------------------------- |
||
271 | 60 |
||
272 | 61 SET A=B |
||
273 | 62 SET A=C |
||
274 | 63 SET A=D |
||
275 | 64 SET A=Din |
||
276 | 65 SET A=Din.0 |
||
277 | 66 SET A=Din.1 |
||
278 | 67 SET A=Din.2 |
||
279 | 68 SET A=Din.3 |
||
280 | 69 SET A=AD1 |
||
281 | 6A SET A=AD2 |
||
282 | 6B |
||
283 | 6C |
||
284 | 6D |
||
285 | 6E |
||
286 | 6F |
||
287 | *) |
||
288 | case Instruction of |
||
289 | $61: FRegA := FRegB; // SET A=B |
||
290 | $62: FRegA := FRegC; // SET A=C |
||
291 | $63: FRegA := FRegD; // SET A=D |
||
292 | $64: FRegA := DIn; // SET A=Din |
||
293 | $65: FRegA := (DIn and 1) shr 0; // SET A=Din.0 |
||
294 | $66: FRegA := (DIn and 2) shr 1; // SET A=Din.1 |
||
295 | $67: FRegA := (DIn and 4) shr 1; // SET A=Din.2 |
||
296 | $68: FRegA := (DIn and 8) shr 1; // SET A=Din.3 |
||
297 | $69: FRegA := AD1; |
||
298 | $6A: FRegA := AD2; |
||
299 | end; |
||
300 | |||
301 | (* |
||
302 | ---------------------------------------------------- |
||
303 | Code Assembly Alternative Comment |
||
304 | ---------------------------------------------------- |
||
305 | 70 |
||
306 | 71 SET A=A+1 |
||
307 | 72 SET A=A-1 |
||
308 | 73 SET A=A+B |
||
309 | 74 SET A=A-B |
||
310 | 75 SET A=A*B |
||
311 | 76 SET A=A/B |
||
312 | 77 SET A=A&B AND |
||
313 | 78 SET A=A|B OR |
||
314 | 79 SET A=A^B XOR |
||
315 | 7A SET A=~A NOT |
||
316 | 7B |
||
317 | 7C |
||
318 | 7D |
||
319 | 7E |
||
320 | 7F |
||
321 | *) |
||
322 | case Instruction of |
||
323 | $71: FRegA := FRegA + 1; // SET A=A+1 |
||
324 | $72: FRegA := FRegA - 1; // SET A=A-1 |
||
325 | $73: FRegA := FRegA + FRegB; // SET A=A+B |
||
326 | $74: FRegA := FRegA - FRegB; // SET A=A-B |
||
327 | $75: FRegA := FRegA * FRegB; // SET A=A*B |
||
328 | $76: begin |
||
329 | if FRegB = 0 then |
||
330 | FRegA := $F // this is the actual behavior of the microchip (program 40 51 45 76 54 30) |
||
331 | else |
||
332 | FRegA := FRegA div FRegB; // SET A=A/B |
||
333 | end; |
||
334 | $77: FRegA := FRegA and FRegB; // SET A=A&B AND |
||
335 | $78: FRegA := FRegA or FRegB; // SET A=A|B OR |
||
336 | $79: FRegA := FRegA xor FRegB; // SET A=A^B XOR |
||
337 | $7A: FRegA := not FRegA; // SET A=~A NOT |
||
338 | end; |
||
339 | |||
340 | (* |
||
341 | ---------------------------------------------------- |
||
342 | Code Assembly Alternative Comment |
||
343 | ---------------------------------------------------- |
||
344 | 80 PAGE 0 Page is used by JUMP, CALL, CTIMES and DTIMES |
||
345 | 81 PAGE 1 |
||
346 | 82 PAGE 2 |
||
347 | 83 PAGE 3 |
||
348 | 84 PAGE 4 |
||
349 | 85 PAGE 5 |
||
350 | 86 PAGE 6 |
||
351 | 87 PAGE 7 |
||
352 | 88 PAGE 8 |
||
353 | 89 PAGE 9 |
||
354 | 8A PAGE A |
||
355 | 8B PAGE B |
||
356 | 8C PAGE C |
||
357 | 8D PAGE D |
||
358 | 8E PAGE E |
||
359 | 8F PAGE F |
||
360 | *) |
||
361 | if (Instruction >= $80) and (Instruction <= $8F) then |
||
362 | begin |
||
363 | FPage := Instruction and $F; |
||
364 | end; |
||
365 | |||
366 | (* |
||
367 | ---------------------------------------------------- |
||
368 | Code Assembly Alternative Comment |
||
369 | ---------------------------------------------------- |
||
370 | 90 JUMP <PAGE>0 |
||
371 | 91 JUMP <PAGE>1 |
||
372 | 92 JUMP <PAGE>2 |
||
373 | 93 JUMP <PAGE>3 |
||
374 | 94 JUMP <PAGE>4 |
||
375 | 95 JUMP <PAGE>5 |
||
376 | 96 JUMP <PAGE>6 |
||
377 | 97 JUMP <PAGE>7 |
||
378 | 98 JUMP <PAGE>8 |
||
379 | 99 JUMP <PAGE>9 |
||
380 | 9A JUMP <PAGE>A |
||
381 | 9B JUMP <PAGE>B |
||
382 | 9C JUMP <PAGE>C |
||
383 | 9D JUMP <PAGE>D |
||
384 | 9E JUMP <PAGE>E |
||
385 | 9F JUMP <PAGE>F |
||
386 | *) |
||
387 | if (Instruction >= $90) and (Instruction <= $9F) then |
||
388 | begin |
||
389 | ProgramCounterNext := (FPage shl 4) + (Instruction and $F); |
||
390 | end; |
||
391 | |||
392 | (* |
||
393 | ---------------------------------------------------- |
||
394 | Code Assembly Alternative Comment |
||
395 | ---------------------------------------------------- |
||
396 | A0 CTIMES <PAGE>0 IF C>0 THEN ( C=C-1 ; JUMP <PAGE>X ) ELSE CONTINUE |
||
397 | A1 CTIMES <PAGE>1 |
||
398 | A2 CTIMES <PAGE>2 |
||
399 | A3 CTIMES <PAGE>3 |
||
400 | A4 CTIMES <PAGE>4 |
||
401 | A5 CTIMES <PAGE>5 |
||
402 | A6 CTIMES <PAGE>6 |
||
403 | A7 CTIMES <PAGE>7 |
||
404 | A8 CTIMES <PAGE>8 |
||
405 | A9 CTIMES <PAGE>9 |
||
406 | AA CTIMES <PAGE>A |
||
407 | AB CTIMES <PAGE>B |
||
408 | AC CTIMES <PAGE>C |
||
409 | AD CTIMES <PAGE>D |
||
410 | AE CTIMES <PAGE>E |
||
411 | AF CTIMES <PAGE>F |
||
412 | *) |
||
413 | if (Instruction >= $A0) and (Instruction <= $AF) then |
||
414 | begin |
||
415 | if FRegC > 0 then |
||
416 | begin |
||
417 | Dec(FRegC); |
||
418 | FReturnAddress := ProgramCounterCurrent; |
||
419 | ProgramCounterNext := (FPage shl 4) + (Instruction and $F); |
||
420 | end; |
||
421 | end; |
||
422 | |||
423 | (* |
||
424 | ---------------------------------------------------- |
||
425 | Code Assembly Alternative Comment |
||
426 | ---------------------------------------------------- |
||
427 | B0 DTIMES <PAGE>0 IF D>0 THEN ( D=D-1 ; JUMP <PAGE>X ) ELSE CONTINUE |
||
428 | B1 DTIMES <PAGE>1 |
||
429 | B2 DTIMES <PAGE>2 |
||
430 | B3 DTIMES <PAGE>3 |
||
431 | B4 DTIMES <PAGE>4 |
||
432 | B5 DTIMES <PAGE>5 |
||
433 | B6 DTIMES <PAGE>6 |
||
434 | B7 DTIMES <PAGE>7 |
||
435 | B8 DTIMES <PAGE>8 |
||
436 | B9 DTIMES <PAGE>9 |
||
437 | BA DTIMES <PAGE>A |
||
438 | BB DTIMES <PAGE>B |
||
439 | BC DTIMES <PAGE>C |
||
440 | BD DTIMES <PAGE>D |
||
441 | BE DTIMES <PAGE>E |
||
442 | BF DTIMES <PAGE>F |
||
443 | *) |
||
444 | if (Instruction >= $B0) and (Instruction <= $BF) then |
||
445 | begin |
||
446 | if FRegD > 0 then |
||
447 | begin |
||
448 | Dec(FRegD); |
||
449 | FReturnAddress := ProgramCounterCurrent; |
||
450 | ProgramCounterNext := (FPage shl 4) + (Instruction and $F); |
||
451 | end; |
||
452 | end; |
||
453 | |||
454 | (* |
||
455 | ---------------------------------------------------- |
||
456 | Code Assembly Alternative Comment |
||
457 | ---------------------------------------------------- |
||
458 | C0 |
||
459 | C1 SKIP_IF A>B |
||
460 | C2 SKIP_IF A<B |
||
461 | C3 SKIP_IF A=B |
||
462 | C4 SKIP_IF Din.0=1 |
||
463 | C5 SKIP_IF Din.1=1 |
||
464 | C6 SKIP_IF Din.2=1 |
||
465 | C7 SKIP_IF Din.3=1 |
||
466 | C8 SKIP_IF Din.0=0 |
||
467 | C9 SKIP_IF Din.1=0 |
||
468 | CA SKIP_IF Din.2=0 |
||
469 | CB SKIP_IF Din.3=0 |
||
470 | CC SKIP_IF S1=0 |
||
471 | CD SKIP_IF S2=0 |
||
472 | CE SKIP_IF S1=1 |
||
473 | CF SKIP_IF S2=1 |
||
474 | *) |
||
475 | case Instruction of |
||
476 | $C1: if FRegA > FRegB then Inc(ProgramCounterNext); |
||
477 | $C2: if FRegA < FRegB then Inc(ProgramCounterNext); |
||
478 | $C3: if FRegA = FRegB then Inc(ProgramCounterNext); |
||
479 | $C4: if ((Din and 1) shr 0) = 1 then Inc(ProgramCounterNext); |
||
480 | $C5: if ((Din and 2) shr 1) = 1 then Inc(ProgramCounterNext); |
||
481 | $C6: if ((Din and 4) shr 2) = 1 then Inc(ProgramCounterNext); |
||
482 | $C7: if ((Din and 8) shr 3) = 1 then Inc(ProgramCounterNext); |
||
483 | $C8: if ((Din and 1) shr 0) = 0 then Inc(ProgramCounterNext); |
||
484 | $C9: if ((Din and 2) shr 1) = 0 then Inc(ProgramCounterNext); |
||
485 | $CA: if ((Din and 4) shr 2) = 0 then Inc(ProgramCounterNext); |
||
486 | $CB: if ((Din and 8) shr 3) = 0 then Inc(ProgramCounterNext); |
||
487 | $CC: if S1 = false then Inc(ProgramCounterNext); |
||
488 | $CD: if S2 = false then Inc(ProgramCounterNext); |
||
489 | $CE: if S1 = true then Inc(ProgramCounterNext); |
||
490 | $CF: if S2 = true then Inc(ProgramCounterNext); |
||
491 | end; |
||
492 | |||
493 | (* |
||
494 | ---------------------------------------------------- |
||
495 | Code Assembly Alternative Comment |
||
496 | ---------------------------------------------------- |
||
497 | D0 CALL <PAGE>0 |
||
498 | D1 CALL <PAGE>1 |
||
499 | D2 CALL <PAGE>2 |
||
500 | D3 CALL <PAGE>3 |
||
501 | D4 CALL <PAGE>4 |
||
502 | D5 CALL <PAGE>5 |
||
503 | D6 CALL <PAGE>6 |
||
504 | D7 CALL <PAGE>7 |
||
505 | D8 CALL <PAGE>8 |
||
506 | D9 CALL <PAGE>9 |
||
507 | DA CALL <PAGE>A |
||
508 | DB CALL <PAGE>B |
||
509 | DC CALL <PAGE>C |
||
510 | DD CALL <PAGE>D |
||
511 | DE CALL <PAGE>E |
||
512 | DF CALL <PAGE>F |
||
513 | *) |
||
514 | if (Instruction >= $D0) and (Instruction <= $DF) then |
||
515 | begin |
||
516 | FCalledOnce := true; |
||
517 | FReturnAddress := ProgramCounterNext; |
||
518 | ProgramCounterNext := (FPage shl 4) + (Instruction and $F) |
||
519 | end; |
||
520 | |||
521 | (* |
||
522 | ---------------------------------------------------- |
||
523 | Code Assembly Alternative Comment |
||
524 | ---------------------------------------------------- |
||
525 | E0 RET |
||
526 | *) |
||
527 | if Instruction = $E0 then |
||
528 | begin |
||
529 | if not FCalledOnce then |
||
530 | begin |
||
531 | // "Freeze" is the behavior of the actual chip (see test program 41 54 27 42 54 27 E0 7A 27 54 33) |
||
532 | ProgramCounterNext := ProgramCounterCurrent; |
||
533 | end |
||
534 | else |
||
535 | begin |
||
536 | ProgramCounterNext := FReturnAddress; |
||
537 | end; |
||
538 | end; |
||
539 | finally |
||
540 | FPC := ProgramCounterNext; |
||
541 | end; |
||
542 | end; |
||
543 | |||
544 | procedure THT46F47.WaitMs(milliseconds: integer); |
||
545 | begin |
||
3 | daniel-mar | 546 | if Assigned(FOnWait) then |
547 | FOnWait(milliseconds) |
||
548 | else |
||
549 | Sleep(milliseconds); |
||
2 | daniel-mar | 550 | end; |
551 | |||
552 | end. |