home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
microcrn
/
issue_40.arc
/
SCANNER.ARC
/
SCAN.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-01-11
|
9KB
|
246 lines
; Code from Pascal column in Micro Cornucopia Issue #39
;
; SCAN.ASM
;
;
; Document scanner resident data capture software.
; This software intercepts the real time clock interrupt
; with a high speed data capture routine and also installs
; a routine at interrupt vector 60H to provide scanning
; functions to other programs.
;
; Since this software incorporates itself into the real time
; clock processing, it has the potential of interfering with
; other resident software. It is highly recommended that
; the absolute minimum of other resident software be installed.
;
; The software does NOT check for previous use of INT 60H.
;
; Written for Eric Isaacson's A86 assembler.
;
; CONST
; joystick = 201H;
; tickconst = 1024;
;
joystick equ 201h
tickconst equ 1024
;
code segment ; both code and data in same segment
;
jmp init
;
; VAR
; count : CARDINAL;
; counter : CARDINAL;
; rasterPtr : POINTER TO raster;
; scaning : BOOLEAN;
; dosclk : ADDRESS;
; tickcount : BYTE;
; tickinc : BYTE;
;
count dw ?
counter dw ?
;
raster_ofs dw
rasterPtr dd ? ; double word for far data
scanning db 0 ; FALSE
;
dosclk_ip dw
dosclk dd ? ; double word for far calls
;
tickcount dw ? ; how many counter cycles?
tickinc dw tickconst ; fast clock divisor default value
;
; Restore/Set hardware clock chip
;
restore_clock: xor ax,ax ; normal time constant = 0
setclk: push ax
mov al,36h ; control register
out 43h,al
pop ax
out 40h,al ; count low byte
xchg ah,al
out 40h,al ; and high byte
ret
;
; New clock routine, includes data capture from scanner
;
fastclock: push ax ; interrupt routine, save registers
push ds
push es
push cs ; make ds = cs
pop ds
;
mov al,scanning ; are we scanning?
or al,al
jz notscanning ; if z, no
;
push bx ; scanning, save additional regs
push cx
push dx
;
mov bx,raster_ofs ; data address offset
mov ax,raster_ofs+2 ; and segment previously set
mov es,ax ; when scan initiated.
;
mov dx,joystick ; input data address
in al,dx ; get the data
mov cl,4 ; then shift to low order nybble
ror al,cl
and al,0fh
;
push si
mov si,counter
es mov b [bx+si],al ; store the data where M2 needs it
pop si
inc w counter ; bump the count
mov ax,count ; done yet?
cmp ax,counter
jnz notdone ; not done yet
;
xor al,al ; done, flip flag
mov scanning,al
call restore_clock ; reset hardware
mov tickcount,0 ; ready for next time
pop dx
pop cx
pop bx
jmp clkexit
;
notdone: pop dx
pop cx
pop bx
;
mov ax,tickcount
add ax,tickinc ; bump tick counter
mov tickcount,ax
jnc clkexit ; if no overflow, not time for DOS
;
notscanning:pushf ; simulate software interrupt
call dosclk ; with pushf and far call
jmp clkxit2 ; skip eoi to 8259 since dos does it
;
clkexit: mov al,20h ; end of interrupt command
out 20h,al ; to 8259 interrupt controller
clkxit2: pop es ; restore registers
pop ds
pop ax
iret
;
; Modula-2 activates the functions in this resident
; software with an int 60H instruction. The parameters
; needed are passed in the registers AL, BX, CX, and DX.
; AL = function #
; BX = data (raster) offset
; DX = data segment
; CX = number of data points to capture or time constant
;
; The functions currently supported are:
; 0 : report address of 'scanning' flag byte (DX:BX)
; 1 : restore original clock routine
; 2 : capture a scan line of data
; 3 : set fast clock speed
;
dispatch: ; M2 call has saved all regs
or al,al ; report flag address?
jz rprt_addr
;
cmp al,1 ; restore clock to normal?
jz killfast
;
cmp al,2 ; get data
jz capture
;
cmp al,3 ; set fast clock divisor
jz setfast
;
iret ; unrecognized function, ignore
;
rprt_addr: push ds
push cs ; data in code segment
pop dx ; segment address
mov bx, offset scanning ; and offset
pop ds ; that's all it takes
iret
;
setfast: push ds ; set fast clock divisor
push cs
pop ds
mov tickinc,cx ; simple isn't it?
pop ds
iret
;
killfast: push ds
push cs
pop ds
call restore_clock ; reset hardware
mov dx,dosclk_ip ; old offset value
mov ds,dosclk_ip+2 ; and old segment
mov ah,25h
mov al,8
sti ; can we do an int if disabled?
int 21h
pop ds
iret
;
; Capture a line of data by setting scanning to TRUE
; and activating the fast clock.
;
capture: push ds
push cs
pop ds
mov counter,0 ; data point counter
mov count,cx ; # points to capture
mov raster_ofs,bx ; data destination offset
mov raster_ofs+2,dx ; and segment
mov scanning,0ffh ; set scanning to TRUE
;
;
mov ax,tickinc ; set clock to fast rate
call setclk
mov tickcount,0 ; reset tick counter
pop ds ; return to M2
iret
;
;
; Install function dispatch routine
;
init: mov ah,25h ; install interrupt function
mov al,60H ; can only use 60 - 67
mov dx, offset dispatch
push cs
pop ds
int 21h
;
; Get and save old clock vector
;
push es
mov ah,35h ; get vector function
mov al,8h ; clock vector #
int 21h
mov dosclk_ip,bx ; save the long address
mov dosclk_ip+2,es
pop es
;
; Install new clock routine
;
push ds
mov ah,25h ; install interrupt fxn
mov al,8h
mov dx, offset fastclock
push cs
pop ds
int 21h
pop ds
;
;
; exit to dos, remain resident
;
mov dx,offset init
int 27h ; terminate but stay resident
;
code ends
end