home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mass61.zip / mass.zip / masm61 / DISK3 / SAMPLES / TSR / ALARM.AS$ / ALARM
Text File  |  1992-11-12  |  9KB  |  191 lines

  1. ;* ALARM.ASM - A simple memory-resident program that beeps the speaker
  2. ;* at a prearranged time.  Can be loaded more than once for multiple
  3. ;* alarm settings.  During installation, ALARM establishes a handler
  4. ;* for the timer interrupt (interrupt 08).  It then terminates through
  5. ;* the Terminate-and-Stay-Resident function (function 31h).  After the
  6. ;* alarm sounds, the resident portion of the program retires by setting
  7. ;* a flag that prevents further processing in the handler.
  8.  
  9.         .MODEL tiny                     ; Create ALARM.COM
  10.         .STACK
  11.  
  12.         .CODE
  13.  
  14.         ORG     5Dh                     ; Location of time argument in PSP,
  15. CountDown       LABEL   WORD            ;   converted to number of 5-second
  16.                                         ;   intervals to elapse
  17.         .STARTUP
  18.         jmp     Install                 ; Jump over data and resident code
  19.  
  20. ; Data must be in code segment so it won't be thrown away with Install code.
  21.  
  22. OldTimer        DWORD   ?               ; Address of original timer routine
  23. tick_91         BYTE    91              ; Counts 91 clock ticks (5 seconds)
  24. TimerActiveFlag BYTE    0               ; Active flag for timer handler
  25.  
  26. ;* NewTimer - Handler routine for timer interrupt (interrupt 08).
  27. ;* Decrements CountDown every 5 seconds.  No other action is taken
  28. ;* until CountDown reaches 0, at which time the speaker sounds.
  29.  
  30. NewTimer PROC   FAR
  31.  
  32.         .IF     cs:TimerActiveFlag != 0 ; If timer busy or retired,
  33.         jmp     cs:OldTimer             ;   jump to original timer routine
  34.         .ENDIF
  35.         inc     cs:TimerActiveFlag      ; Set active flag
  36.         pushf                           ; Simulate interrupt by pushing flags,
  37.         call    cs:OldTimer             ;   then far-calling original routine
  38.         sti                             ; Enable interrupts
  39.         push    ds                      ; Preserve DS register
  40.         push    cs                      ; Point DS to current segment for
  41.         pop     ds                      ;   further memory access
  42.         dec     tick_91                 ; Count down for 91 ticks
  43.         .IF     zero?                   ; If 91 ticks have elapsed,
  44.         mov     tick_91, 91             ;   reset secondary counter and
  45.         dec     CountDown               ;   subtract one 5-second interval
  46.         .IF     zero?                   ; If CountDown drained,
  47.         call    Sound                   ;   sound speaker
  48.         inc     TimerActiveFlag         ; Alarm has sounded, set flag
  49.         .ENDIF
  50.         .ENDIF
  51.  
  52.         dec     TimerActiveFlag         ; Decrement active flag
  53.         pop     ds                      ; Recover DS
  54.         iret                            ; Return from interrupt handler
  55.  
  56. NewTimer ENDP
  57.  
  58.  
  59. ;* Sound - Sounds speaker with the following tone and duration:
  60.  
  61. BEEP_TONE       EQU     440             ; Beep tone in hertz
  62. BEEP_DURATION   EQU     6               ; Number of clocks during beep,
  63.                                         ;   where 18 clocks = approx 1 second
  64.  
  65. Sound   PROC    USES ax bx cx dx es     ; Save registers used in this routine
  66.         mov     al, 0B6h                ; Initialize channel 2 of
  67.         out     43h, al                 ;   timer chip
  68.         mov     dx, 12h                 ; Divide 1,193,180 hertz
  69.         mov     ax, 34DCh               ;   (clock frequency) by
  70.         mov     bx, BEEP_TONE           ;   desired frequency
  71.         div     bx                      ; Result is timer clock count
  72.         out     42h, al                 ; Low byte of count to timer
  73.         mov     al, ah
  74.         out     42h, al                 ; High byte of count to timer
  75.         in      al, 61h                 ; Read value from port 61h
  76.         or      al, 3                   ; Set first two bits
  77.         out     61h, al                 ; Turn speaker on
  78.  
  79. ; Pause for specified number of clock ticks
  80.  
  81.         mov     dx, BEEP_DURATION       ; Beep duration in clock ticks
  82.         sub     cx, cx                  ; CX:DX = tick count for pause
  83.         mov     es, cx                  ; Point ES to low memory data
  84.         add     dx, es:[46Ch]           ; Add current tick count to CX:DX
  85.         adc     cx, es:[46Eh]           ; Result is target count in CX:DX
  86.         .REPEAT
  87.         mov     bx, es:[46Ch]           ; Now repeatedly poll clock
  88.         mov     ax, es:[46Eh]           ;   count until the target
  89.         sub     bx, dx                  ;   time is reached
  90.         sbb     ax, cx
  91.         .UNTIL  !carry?
  92.  
  93.         in      al, 61h                 ; When time elapses, get port value
  94.         xor     al, 3                   ; Kill bits 0-1 to turn
  95.         out     61h, al                 ;   speaker off
  96.         ret
  97.  
  98. Sound   ENDP
  99.  
  100.  
  101.  
  102. ;* Install - Converts ASCII argument to valid binary number, replaces
  103. ;* NewTimer as the interrupt handler for the timer, then makes program
  104. ;* memory resident by exiting through function 31h.
  105. ;*
  106. ;* This procedure marks the end of the TSR's resident section and the
  107. ;* beginning of the installation section.  When ALARM terminates through
  108. ;* function 31h, the above code and data remain resident in memory.  The
  109. ;* memory occupied by the following code is returned to DOS.
  110.  
  111.  
  112. Install PROC
  113.  
  114. ; Time argument is in hhmm military format.  Convert ASCII digits to
  115. ; number of minutes since midnight, then convert current time to number
  116. ; of minutes since midnight.  Difference is number of minutes to elapse
  117. ; until alarm sounds.  Convert to seconds-to-elapse, divide by 5 seconds,
  118. ; and store result in word CountDown.
  119.  
  120. DEFAULT_TIME    EQU     3600            ; Default alarm setting = 1 hour
  121.                                         ;   (in seconds) from present time
  122.         mov     ax, DEFAULT_TIME
  123.         cwd                             ; DX:AX = default time in seconds
  124.         .IF     BYTE PTR CountDown != ' ';If not blank argument,
  125.         xor     CountDown[0], '00'      ;   convert 4 bytes of ASCII
  126.         xor     CountDown[2], '00'      ;   argument to binary
  127.                                         
  128.         mov     al, 10                  ; Multiply 1st hour digit by 10
  129.         mul     BYTE PTR CountDown[0]   ;   and add to 2nd hour digit
  130.         add     al, BYTE PTR CountDown[1]
  131.         mov     bh, al                  ; BH = hour for alarm to go off
  132.         mov     al, 10                  ; Repeat procedure for minutes
  133.         mul     BYTE PTR CountDown[2]   ; Multiply 1st minute digit by 10
  134.         add     al, BYTE PTR CountDown[3] ;   and add to 2nd minute digit
  135.         mov     bl, al                  ; BL = minute for alarm to go off
  136.         mov     ah, 2Ch                 ; Request function 2Ch
  137.         int     21h                     ; Get Time (CX = current hour/min)
  138.         mov     dl, dh
  139.         sub     dh, dh
  140.         push    dx                      ; Save DX = current seconds
  141.  
  142.         mov     al, 60                  ; Multiply current hour by 60
  143.         mul     ch                      ;   to convert to minutes
  144.         sub     ch, ch
  145.         add     cx, ax                  ; Add current minutes to result
  146.                                         ; CX = minutes since midnight
  147.         mov     al, 60                  ; Multiply alarm hour by 60
  148.         mul     bh                      ;   to convert to minutes
  149.         sub     bh, bh
  150.         add     ax, bx                  ; AX = number of minutes since
  151.                                         ;   midnight for alarm setting
  152.         sub     ax, cx                  ; AX = time in minutes to elapse
  153.                                         ;   before alarm sounds
  154.         .IF     carry?                  ; If alarm time is tomorrow,
  155.         add     ax, 24 * 60             ;   add minutes in a day
  156.         .ENDIF
  157.  
  158.         mov     bx, 60
  159.         mul     bx                      ; DX:AX = minutes-to-elapse-times-60
  160.         pop     bx                      ; Recover current seconds
  161.         sub     ax, bx                  ; DX:AX = seconds to elapse before
  162.         sbb     dx, 0                   ;   alarm activates
  163.         .IF     carry?                  ; If negative,
  164.         mov     ax, 5                   ;   assume 5 seconds
  165.         cwd
  166.         .ENDIF
  167.         .ENDIF
  168.  
  169.         mov     bx, 5                   ; Divide result by 5 seconds
  170.         div     bx                      ; AX = number of 5-second intervals
  171.         mov     CountDown, ax           ;   to elapse before alarm sounds
  172.  
  173.         mov     ax, 3508h               ; Request function 35h
  174.         int     21h                     ; Get vector for timer (interrupt 08)
  175.         mov     WORD PTR OldTimer[0], bx; Store address of original
  176.         mov     WORD PTR OldTimer[2], es;   timer interrupt
  177.         mov     ax, 2508h               ; Request function 25h
  178.         mov     dx, OFFSET NewTimer     ; DS:DX points to new timer handler
  179.         int     21h                     ; Set vector with address of NewTimer
  180.  
  181.         mov     dx, OFFSET Install      ; DX = bytes in resident section
  182.         mov     cl, 4
  183.         shr     dx, cl                  ; Convert to number of paragraphs
  184.         inc     dx                      ;   plus one
  185.         mov     ax, 3100h               ; Request function 31h, error code=0
  186.         int     21h                     ; Terminate-and-Stay-Resident
  187.  
  188. Install ENDP
  189.  
  190.         END
  191.