home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SDN¹ Plus
/
SDN1_.cdr
/
sdn
/
other
/
mimic11.sdn
/
MINT.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-03-13
|
7KB
|
178 lines
; MINT.ASM Version 1.0
; (c) 1990 Eletech Electronics, Inc. All rights UNreserved.
;
; Creation : 3-13-90 by Wei Lu.
; Function : Works with MIMIC.C to play Eletech Digicorder recorded voice
; file thru PC's internal speaker at specified sampling rate.
; Usage : See MIMIC.C.
; Assembler: Microsoft MASM 5.0 and up.
; Assembling Options: None.
;
; Operation: MINT.ASM is an interrupt handler. After MIMIC.C re-directs clock
; interrupt, subsequent timer 0 interrupts are intercepted and
; handled by MINT.ASM.
;
; MINT.ASM has two responsibilities:
;
; a. Output voice data bit by bit to PC's speaker upon each timer
; 0 interrupt.
;
; b. Maintain DOS clock operation by doing "real" clock interrupts
; 18.2 times per second.
;
; MINT.ASM assumes that MIMIC.C has done the following setup:
;
; a. Load voice data into play buffer pointed to by play_addr.
;
; b. Calculate and set play_ptr, play_length and tack_count (see
; MIMIC.C for explanations.)
;
; c. Re-direct timer 0 (clock) interrupt and re-program timer 0
; interrupt rate to equal sampling rate.
;
; Upon each timer 0 interrupt, MINT.ASM will be activated and do
; one of the following:
;
; a. If there is no more data to play, do a "real" clock interrupt
; if it's time to, then terminate.
;
; Otherwise,
;
; b. If it does not need a new byte of data, output a bit and
; terminate.
;
; c. If it needs a new byte of data but it's not time yet to do a
; "real" clock interrupt, get a byte, output a bit and
; terminate.
;
; d. If it needs a new byte of data and it's also time to do a
; "real" clock interrupt, get a byte, output a bit, do a "real"
; clock interrupt and terminate.
;
; The following codes are written so as to minimize the execution
; time of case b above. See MIMIC.C for more operation details.
.model small
public _int_handler
public _play_addr
public _play_ptr
public _play_length
public _tack_count
speaker equ 97 ; speaker I/O port
ocw2 equ 20h ; 8259 control I/O port
eoi equ 20h ; "End Of Interrupt" control word
clock_irq equ 255 ; "real" clock new interrupt #
.data
_play_addr label dword ; play buffer is 64K bytes
_play_ptr label word ; actually the offset of play_addr
play_addr label dword ; (set and changed by MIMIC.C)
play_addr_off dw ?
play_addr_seg dw ? ; does not change once set
_play_length label word ; number of bytes to play
play_length dw ?
_tack_count label byte ; see MIMIC.C
tack_count db ?
data_byte db 55 ; a byte of garbage doesn't hurt
bit_ptr db 80h ; bits go from left to right
t_count db ? ; a working copy of tack_count
.code
_int_handler proc far
push ax
push ds
mov ax,@data
mov ds,ax
cmp play_length,0 ; are we out of voice data?
je no_more
mov al,data_byte
mov ah,bit_ptr ; bit_ptr used as a mask
and al,ah ; is this bit 0 or 1?
jz zero
one:
nop ; so that "one" and "zero" take
nop ; the same amount of time to do
mov al,01001010b ; (optimized for AT)
out speaker,al
ror ah,1 ; will set Carry if rotate around
mov bit_ptr,ah ; update bit_ptr
jc adjust
mov al,eoi
out ocw2,al ; re-enable interrupt requests
pop ds
pop ax
iret
zero:
mov al,01001000b
out speaker,al
ror ah,1
mov bit_ptr,ah
jc adjust
mov al,eoi
out ocw2,al
pop ds
pop ax
iret
adjust: ; now we have to get a new byte
sub play_length,1 ; also update play_length
push si
push es
les si,dword ptr ds:play_addr
mov al,byte ptr es:[si]
mov data_byte,al ; the new byte is in
inc si
mov play_addr_off,si ; update play_ptr
dec t_count ; is it time to do clock int?
jz do_interrupt
mov al,eoi
out ocw2,al
pop es
pop si
pop ds
pop ax
iret
do_interrupt:
mov al,tack_count
mov t_count,al ; reset t_count to tack_count
int clock_irq ; do clock interrupt
pop es ; no need to re-enable interrupt
pop si ; requests since it's already
pop ds ; been done in clock interrupt
pop ax ; service routine
iret
no_more:
ror bit_ptr,1 ; still have to know when to do
jc adj ; clock interrupt
mov al,eoi
out ocw2,al
pop ds
pop ax
iret
adj:
dec t_count
jz do_int
mov al,eoi
out ocw2,al
pop ds
pop ax
iret
do_int:
mov al,tack_count
mov t_count,al
int clock_irq
pop ds
pop ax
iret
_int_handler endp
end