OBJNAM WAIT.SBR ; Last modified 30-Dec-85
; Subroutine to WAIT for specified number of seconds (can use fractions)
; by Irv Bromberg, Medic/OS Consultants, Toronto, CANADA
RADIX 10
VEDIT=11
VMINOR=1
VMAJOR=5
VSUB=0

IF EQ,1

Calling syntax: XCALL WAIT {,Delay}

where Delay is a floating point or string parameter containing a decimal
delay value in seconds (fractional parts may be used). This version of
WAIT.SBR waits for OIP to finish before starting the delay. If Delay=0
or no parameters are passed subroutine simply returns after waiting for
OIP to clear. If the operator hits ^C the sleeping is aborted at the end
of the current 100th of a second.

Advantages over Alpha Micro's SLEEP.SBR:

Control-C can abort the sleep period. Waits for output-in-progress to
the user's terminal to finish before starting the sleep.  Does the OIP
wait even if no parameters are passed or the delay=0, can be used to
make sure output has flushed before continuing (for example if next step
will modify user's terminal status word).  Changes JOBPRG(JCB) to [WAIT]
when the system is in "test" mode (using SET TEST command) while
waiting, so SYSTAT or STAT can display what the job is doing (restores
JOBPRG after delay complete).

ENDC

SEARCH SYS
SEARCH SYSSYM
SEARCH TRM

Impure=A0
JCB=A1
Value=A2
ArgBas=A3
Worksp=A4
TCB=A5
Atemp=A6
Source=A6

Ticks=D1

; SY$TST=256    ; remove semi-colon before this equate if assembling on
               ; system with AMOS/L version prior to 1.3

SCALE=128       ; offset to SCALE factor in BASIC Impure Workspace

       PHDR    -1,0,PH$REE!PH$REU

       MOV     JOBCUR,JCB              ; index user's Job Control Block
       MOV     JOBTRM(JCB),TCB         ; index user's Terminal Control Block
       PUSH    JOBPRG(JCB)             ; save current JOBPRG
       MOV     SYSTEM,D7               ; is system in "test" mode?
       AND     #SY$TST,D7              ; if so then change JOBPRG=[WAIT]
       BEQ     WaitOIP                 ; note this has no effect under AMOS/L
       MOV     #<[WAI]_16+[T  ]>,JOBPRG(JCB) ; versions prior to 1.3 unless
                                       ; the user has a program to set SY$TST

WaitOIP:TSTB    T.STS(TCB)              ; wait for OIP to clear before delay
       BPL     GetVal
       SLEEP   #500                    ; 50ms wait each time around loop
       BR      WaitOIP

GetVal: TSTW    @ArgBas                 ; wait only for OIP to clear if no
       BEQ     Done                    ; parameter is passed
       TST     8(ArgBas)               ; check parameter size
       BEQ     Done                    ; NULL parameter, wait only for OIP
       CMPW    2(ArgBas),#4            ; is it floating parameter?
       BNE     Done                    ; no, wait only for OIP

GetFlt: SUB     #6,SP                   ; get some workspace
       MOV     SP,Worksp
       MOV     4(ArgBas),Source        ; get desired seconds to sleep
       MOVB    (Source)+,(Worksp)+
       MOVB    (Source)+,(Worksp)+
       MOVB    (Source)+,(Worksp)+
       MOVB    (Source)+,(Worksp)+
       MOVB    (Source)+,(Worksp)+
       MOVB    (Source)+,(Worksp)+
       MOV     SP,Worksp               ; restore pointer
       MOV     Scale(Impure),D7        ; scale factor in use?
       NEG     D7                      ; if so we have to unscale the value
       ADD     #2,D7                   ; but multiply to 100ths of second
       BEQ     10$                     ; could be zero if SCALE 2 if effect
       FPWR    @Worksp,D7
10$:    FFTOL   @Worksp,Ticks           ; convert to longword
       ADD     #6,SP                   ; return the workspace
       TST     Ticks
       BEQ     Done                    ; quit if 0 delay requested
Loop:   SLEEP   #96                     ; sleep 1/100s (-4 for overhead)
       TSTB    JOBSTS(JCB)             ; ^C pending?
       BMI     Done                    ; yes, abort
       DEC     Ticks                   ; countdown
       BNE     Loop                    ; more if not zero yet

Done:   POP     JOBPRG(JCB)
       RTN

       END