home *** CD-ROM | disk | FTP | other *** search
- 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.
-
- {=============================================================================}