[Back to MISC SWAG index] [Back to Main SWAG index] [Original]
unit RJScan;
{******************************}
{ }
{ RJScan }
{ }
{ v1.1 }
{ }
{ }
{ by }
{ }
{ Roland Skinner }
{ }
{ Copyright (c) 1992 }
{ }
{ RJS Software }
{ }
{ Released to the public }
{ domain 1994. }
{ }
{******************************}
{ Implements scanning ability for the DFI HS-3000 PLUS HANDY SCANNER or }
{ other 100% compatible hand-scanners (including certain GeniScans). }
{ NOTE - This unit may be overlayed. }
{ - This unit requires Turbo Pascal 6 (or above). }
{$B-,D-,F+,G-,I-,L-,O+,R-,S-,V-,X-}
{=============================================================================}
interface
{-----------------------------------------------------------------------------}
const
AnyResolution = 0;
{-----------------------------------------------------------------------------}
type
ScanError = (scOK,scNoScanner,scInvalidResolution,scIncorrectResolution,
scInvalidImageWidth);
{-----------------------------------------------------------------------------}
type
ScanLineBufferProc = function(LineNumber : Integer) : Pointer;
{ NOTE - This function should return the address }
{ of the scan-buffer for the "LineNumber"th }
{ line. First line is number 0. }
DisplayScannedLineProc = procedure(LineNumber : Integer);
{ NOTE - This procedure should display (if }
{ necessary) the "LineNumber"th line }
{ that was scanned in. First line is }
{ number 0. }
StopScanningProc = function : Boolean;
{ NOTE - This function should return "False", unless }
{ some event has occurred which requires }
{ scanning to stop. }
{-----------------------------------------------------------------------------}
function ScanImage(DesiredResolution,MaxLinesToScan,BytesPerLine : Integer;
ScanLineBuffer : ScanLineBufferProc;
DisplayScannedLine : DisplayScannedLineProc;
StopScanning : StopScanningProc) : ScanError;
{- This function will scan an image with width 8*"BytesPerLine" and }
{ height "MaxLinesToScan". It is possible to specify the resolution at }
{ which to scan the image in "DesiredResolution" (100,200,300,400). }
{ If the resolution set on the scanner is different to that specified, }
{ then the "scIncorrectResolution" error will be returned. }
{ If "DesiredResolution" is "AnyResolution", then any resolution will }
{ be allowed. "scInvalidResolution" will be returned if a resolution }
{ other than 100,200,300,400 or "AnyResolution" is specified. }
{ "ScanLineBuffer", "DisplayScannedLine" and "StopScanning" are }
{ procedures/functions whose functions are discussed above. These must }
{ be FAR procedures/functions. }
{ If "BytesPerLine" is too large for the scanner-resolution, then }
{ "scInvalidImageWidth" will be returned. }
{ If scanner is not installed then "scNoScanner" is returned. }
{ If successful, then "scOK" will be returned. }
{ This function may not work with certain hand-scanners (if so, use }
{ "GenericScanImage"). }
function GenericScanImage(MaxLinesToScan,BytesPerLine : Integer;
ScanLineBuffer : ScanLineBufferProc;
DisplayScannedLine : DisplayScannedLineProc;
StopScanning : StopScanningProc) : ScanError;
{- This function will scan an image in an analogous manner as }
{ "ScanImage". However, it does not do any checks for valid resolution }
{ or image-width. This is to allow compatibility for scanners which do }
{ not allow for scan-resolution selection. }
{ "scOK", "scNoScanner" and "scInvalidImageWidth" may be returned by }
{ this function. Refer to "ScanImage" for a discussion about these. }
function ScannerIsInstalled : Boolean;
{- Returns installed-status of scanner. }
function ResolutionOfScanner : Integer;
{- Returns the resolution set on the scanner. If scanner is not }
{ installed, then -1 will be returned. }
{ This function may not work with certain hand-scanners. }
{=============================================================================}
implementation
{-----------------------------------------------------------------------------}
const
MaxBytesPerLine : Array[1..4] of Byte = (50,102,154,205);
{-----------------------------------------------------------------------------}
var
ScannerInstalled : Boolean;
ScannerResolution : Word;
ScannerResolution100 : Byte;
DMAChannel : Byte;
DMAPageRegister : Word;
DMACurAddrRegister : Word;
DMACurWordCountRegister : Word;
DMAClearSingleMaskBit : Byte;
DMASetSingleMaskBit : Byte;
DMAModeRegisterSetting : Byte;
DMAWriteRequest : Byte;
DMATerminalCountReached : Byte;
{-----------------------------------------------------------------------------}
procedure DetermineScannerResolution; assembler;
var
Data : Byte;
asm
xor ax,ax
jmp @Start
@ResSettings:
db 21h,41h,51h,71h
@Start:
mov dx,27Bh
mov cx,300
@1:
in al,dx
and al,10000000b
jnz @1
@2:
in al,dx
and al,10000000b
jz @2
loop @1
@3:
in al,dx
and al,10000000b
jnz @3
@4:
in al,dx
and al,00100100b
shr al,1
shr al,1
or ah,al
shr al,1
shr al,1
or ah,al
and ah,00000011b
xor al,al
xchg al,ah
mov bl,4
sub bl,al
mov al,bl
push ax
mov bx,OFFSET (@ResSettings-1)
add bx,ax
mov al,[cs:bx]
mov dx,27Ah
out dx,al
mov Data,al
pop ax
mov ScannerResolution100,al
mov cx,100
mul cx
mov ScannerResolution,ax
end;
{-----------------------------------------------------------------------------}
procedure DetermineScannerDMA; assembler;
asm
mov dx,27Bh
in al,dx
and al,00001010b
cmp al,00001000b
je @UseDMA1
cmp al,00000010b
je @UseDMA3
jmp @NoDMA
@UseDMA1:
mov DMAChannel,1
mov DMAPageRegister, 83h
mov DMACurAddrRegister, 02h
mov DMACurWordCountRegister,03h
mov DMAClearSingleMaskBit, 00000001b
mov DMASetSingleMaskBit, 00000101b
mov DMAModeRegisterSetting, 01000101b
mov DMAWriteRequest, 00000001b
mov DMATerminalCountReached,00000010b
jmp @Exit
@UseDMA3:
mov DMAChannel,3
mov DMAPageRegister, 82h
mov DMACurAddrRegister, 06h
mov DMACurWordCountRegister,07h
mov DMAClearSingleMaskBit, 00000011b
mov DMASetSingleMaskBit, 00000111b
mov DMAModeRegisterSetting, 01000111b
mov DMAWriteRequest, 00000011b
mov DMATerminalCountReached,00001000b
jmp @Exit
@NoDMA:
mov DMAChannel,0
@Exit:
end;
{-----------------------------------------------------------------------------}
procedure TurnScannerOn; assembler;
asm
mov dx,27Ah
mov al,01h
out dx,al
end;
{-----------------------------------------------------------------------------}
procedure TurnScannerOff; assembler;
asm
mov dx,27Ah
mov al,00h
out dx,al
end;
{-----------------------------------------------------------------------------}
procedure DMADelay; assembler;
asm
nop
nop
nop
end;
{-----------------------------------------------------------------------------}
function DoScan(MaxLinesToScan,BytesPerLine : Integer;
ScanLineBuffer : ScanLineBufferProc;
DisplayScannedLine : DisplayScannedLineProc;
StopScanning : StopScanningProc) : ScanError;
var
LinesScanned : Integer;
ScanBuffer : Pointer;
WidthToScan : Word absolute BytesPerLine;
QuitScanning : Boolean;
begin
if (BytesPerLine>0) and (BytesPerLine<=MaxBytesPerLine[ScannerResolution100]) then
begin
LinesScanned := 0;
QuitScanning := False;
repeat
ScanBuffer := ScanLineBuffer(LinesScanned);
asm
{-Disable DMA transfer }
mov al,DMASetSingleMaskBit
out 0Ah,al
call DMADelay;
mov al,DMAModeRegisterSetting
out 0Bh,al
call DMADelay
{-Setup Buffer address }
les di,ScanBuffer
mov dx,es
mov al,dh
mov cl,4
shl dx,cl
shr al,cl
add dx,di
adc al,0
mov cx,dx
mov dx,DMAPageRegister
out dx,al
call DMADelay
out 0Ch,al
call DMADelay
mov dx,DMACurAddrRegister
mov al,cl
out dx,al
call DMADelay
mov al,ch
out dx,al
call DMADelay
{-Setup bytes to transfer }
out 0Ch,al
call DMADelay
mov ax,WidthToScan
dec ax
mov dx,DMACurWordCountRegister
out dx,al
call DMADelay
mov al,ah
out dx,al
{-Start DMA transfer }
mov dx,27Bh
out dx,al
dec dx
in al,dx { DX = 027Ah }
mov al,DMAWriteRequest
out 09h,al
call DMADelay
mov al,DMAClearSingleMaskBit
out 0Ah,al
end;
{-Scan line }
asm
mov bl,DMATerminalCountReached
@1:
in al,08h
and al,bl
cmp al,bl
je @2
push bx
call StopScanning
pop bx
or al,al
jz @1
mov QuitScanning,True
@2:
end;
DisplayScannedLine(LinesScanned);
Inc(LinesScanned);
until (LinesScanned=MaxLinesToScan) or QuitScanning;
DoScan := scOK;
end
else
DoScan := scInvalidImageWidth;
end;
{-----------------------------------------------------------------------------}
function ScanImage(DesiredResolution,MaxLinesToScan,BytesPerLine : Integer;
ScanLineBuffer : ScanLineBufferProc;
DisplayScannedLine : DisplayScannedLineProc;
StopScanning : StopScanningProc) : ScanError;
begin
if ScannerInstalled then
begin
if (DesiredResolution=AnyResolution) or ((DesiredResolution div 100) in [1..4]) then
begin
TurnScannerOn;
DetermineScannerResolution;
if (DesiredResolution=AnyResolution) or (DesiredResolution=ScannerResolution) then
ScanImage := DoScan(MaxLinesToScan,BytesPerLine,
ScanLineBuffer,DisplayScannedLine,StopScanning)
else
ScanImage := scIncorrectResolution;
TurnScannerOff;
end
else
ScanImage := scInvalidResolution;
end
else
ScanImage := scNoScanner;
end;
{-----------------------------------------------------------------------------}
function GenericScanImage(MaxLinesToScan,BytesPerLine : Integer;
ScanLineBuffer : ScanLineBufferProc;
DisplayScannedLine : DisplayScannedLineProc;
StopScanning : StopScanningProc) : ScanError;
begin
if ScannerInstalled then
begin
TurnScannerOn;
ScannerResolution100 := 4;
GenericScanImage := DoScan(MaxLinesToScan,BytesPerLine,
ScanLineBuffer,DisplayScannedLine,StopScanning);
TurnScannerOff;
end
else
GenericScanImage := scNoScanner;
end;
{-----------------------------------------------------------------------------}
procedure DetermineScannerPresence;
begin
TurnScannerOn;
DetermineScannerDMA;
TurnScannerOff;
ScannerInstalled := (DMAChannel<>0);
end;
{-----------------------------------------------------------------------------}
function ScannerIsInstalled : Boolean;
begin
ScannerIsInstalled := ScannerInstalled;
end;
{-----------------------------------------------------------------------------}
function ResolutionOfScanner : Integer;
begin
if ScannerInstalled then
begin
TurnScannerOn;
DetermineScannerResolution;
TurnScannerOff;
ResolutionOfScanner := ScannerResolution;
end
else
ResolutionOfScanner := -1;
end;
{-----------------------------------------------------------------------------}
begin
DetermineScannerPresence;
end.
{=============================================================================}
[Back to MISC SWAG index] [Back to Main SWAG index] [Original]