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