Rev Author Line No. Line
204 miho 1 unit Delay;
2  
3 {-----------------------------------------------------------------}
4 { Definovane spozdeni, ktere funguje i na }
5 { vykonnejsich pocitacich }
6 { }
7 { Verze 1.0 portovano by miho 96 }
8 { 1.1 popora kratkych casu miho 98 }
9 { 1.2 podpora rychlych CPU ( rozsireni DelayCnt1 na DWORD ) }
10 {-----------------------------------------------------------------}
11  
12 {$I-,S-}
13  
14 interface
15  
16  
17 procedure xDelay(MS: Word);
18 {-- cas uveden v milisekundach --}
19  
20  
21 procedure xDelayMicro(MicroS: Word);
22 {-- cas uveden v mikrosekundach --}
23 { POZOR: Casy jsou vzdy o neco delsi a za normalnich podminek }
24 { je cas delsi radove o nekolik mikrosekund }
25 { ( na PC Pentium 75 to dela cca 6us ). }
26  
27  
28 implementation
29  
30  
31 var DelayCnt1:longint; { kalibrace casu po 1 ms }
32 DelayCnt55:longint; { totez pred vydelenim 55 }
33  
34  
35 procedure DelayLoop;
36 begin
37 asm
38 @@Loop: SUB AX,1 { DX:AX - pocitadlo DWORD }
39 SBB DX,0 { dekrement }
40 JC @@End { doteklo }
41 CMP BL,ES:[DI] { pri uplynuti tiku ( 55ms ) }
42 JE @@Loop { taky koncim }
43 @@End:
44 end;
45 end;
46  
47  
48 procedure Initialize;
49 {-- inicializace - kalibrace casu --}
50 begin
51 asm
52 MOV AX,40H { adresa bunky BIOS DATA s tiky }
53 MOV ES,AX { po 55 ms aktualizuje BIOS }
54 MOV DI,6CH
55 MOV BL,ES:[DI]
56 @@Wait: CMP BL,ES:[DI]
57 JE @@Wait { pockej na cely tik }
58 MOV BL,ES:[DI] { schovej si tik do BL }
59 MOV AX,-28 { piskvorcova konstanta ? asi }
60 CWD
61 CALL DelayLoop { pockej na konec tiku BL }
62 NOT AX { a pocitej cas v DS:AX}
63 NOT DX
64 MOV word ptr [DelayCnt55],AX { uschovej kalibraci }
65 MOV word ptr [DelayCnt55+2],DX
66 end; {asm}
67 DelayCnt1:=DelayCnt55 div 55; { uschovej kalibraci 1 ms }
68 end; {Initialize}
69  
70  
71 procedure xDelay(MS: Word);
72 {-- proved standardni spozdeni merene v milisekundach --}
73 begin
74 asm
75 MOV CX,MS { pocet milisekund }
76 JCXZ @@End { nulova hodnota - hned konci }
77 MOV AX,40H { adresa BIOS COM port - to je }
78 MOV ES,AX { jakakoli bunka, ktera se v }
79 XOR DI,DI { v provozu nemeni aby se netestoval }
80 MOV BL,ES:[DI] { casovac a presto mohla byt }
81 @@Loop: MOV AX,word ptr [DelayCnt1] { procedura DelayLoop stejna }
82 MOV DX,word ptr [DelayCnt1+2] { DX:AX kalibracni konsatnta }
83 CALL DelayLoop { pro spozdeni 1 ms }
84 LOOP @@Loop
85 @@End:
86 end; {asm}
87 end; {xDelay}
88  
89  
90 procedure xDelayMicro(MicroS: Word);
91 {-- procedura pro spozdeni zadavane v mikrosekundach --}
92 label Error;
93 begin {-- prepocitej zadany cas na pocet cyklu --}
94 asm
95 {-- DWORD * WORD / WORD -> DWORD --}
96 SUB DX,DX
97 MOV AX,WORD PTR[DelayCnt55+2]
98 MOV BX,55000
99 MOV CX,MicroS
100 DIV BX
101 PUSH DX
102 MUL CX
103 MOV DI,DX
104 AND DX,DX
105 POP DX
106 JNZ Error
107 MOV AX,WORD PTR[DelayCnt55]
108 DIV BX
109 PUSH DX
110 MUL CX
111 MOV SI,AX
112 ADD DI,DX
113 POP AX
114 JC Error
115 MUL CX
116 DIV BX
117 ADD SI,AX
118 ADC DI,0
119 PUSH SI
120 PUSH DI
121 {-- vlastni spozdeni --}
122 MOV AX,40H { opet konstantni bunka }
123 MOV ES,AX
124 XOR DI,DI
125 MOV BL,ES:[DI]
126 POP DX { DX:AX cas v poctech cyklu }
127 POP AX
128 CALL DelayLoop
129 end; {asm}
130 exit;
131 asm
132 Error: MOV AX,0FFFFH
133 MOV DX,AX
134 CALL DelayLoop
135 end; {asm}
136 end;
137  
138  
139 begin Initialize; { udelej kalibraci }
140 end.