home *** CD-ROM | disk | FTP | other *** search
/ Sound Sensations! / sound_sensations.iso / miscprog / ad-prog / timer.asm < prev    next >
Assembly Source File  |  1990-04-20  |  7KB  |  395 lines

  1.  
  2. ;    Copyright Ad Lib Inc., 1990
  3.  
  4. ;    This file is part of the Ad Lib Programmer's Manual product and is
  5. ;    subject to copyright laws.  As such, you may make copies of this file
  6. ;    only for the purpose of having backup copies.  This file may not be
  7. ;    redistributed in any form whatsoever.
  8.  
  9. ;    If you find yourself in possession of this file without having received
  10. ;    it directly from Ad Lib Inc., then you are in violation of copyright
  11. ;    laws, which is a form of theft.
  12.  
  13. ; TIMER.ASM
  14. ;
  15. ; 08h interrupt driver (from BYTE special issue, nov. 86, pp 249-262)
  16. ;
  17. ; Adaptation: Marc Savary, Ad Lib Inc, 1986/11/03
  18. ;
  19.  
  20. ;    This module allows you to change the timer-0 interrupt rate,
  21. ;   without affecting the rate at which the currently installed
  22. ;   routine is called  (18.2 Hz).
  23. ;
  24. ;   A user function (TimeOut()) is called after 'n'
  25. ;   interrupts, 'n' being reset after each call.
  26.  
  27.  
  28. ; Originally written for Lattice C Compiler, small model.  Adapted to
  29. ; Microsoft by using macros (notably BEGIN, P_END, extrn).  A flag for the
  30. ; type of compiler is defined in the file VERSION.INC.  According to this
  31. ; flag, the file containing the appropriate equates and macros is then
  32. ; included.
  33.  
  34. ; 3-may-89, Dale Glowinski
  35. ; Removed stuff for Lattice interface.  Adapted to MASM V1.51
  36.  
  37.  
  38. .MODEL LARGE
  39.  
  40. ; @codesize is predefined by MASM: 0 = small, compact; 1 = med, large, huge
  41. IF  @codesize
  42.    CPSIZE       EQU  4
  43. ELSE
  44.    CPSIZE       EQU  2
  45. ENDIF
  46.  
  47. clk_int equ 08h     ; timer-0 interrupt vector number
  48.  
  49.  
  50. ; ============= vector structure ==========
  51.  
  52. vector    struc
  53. regip    dw    ?
  54. regcs    dw    ?
  55. vector    ends
  56.  
  57.  
  58. ; ========================= DATA SEGMENT ============================
  59.  
  60. .DATA
  61.  
  62. int_stack_size       equ 512
  63.  
  64. the_stack            db  int_stack_size DUP ('S')
  65. interrupt_stack_top  dw  0
  66.  
  67.  
  68. ;========================== CODE SEGMENT ============================
  69.  
  70. .CODE
  71.  
  72.  
  73. IF  @codesize
  74.    extrn  _TimeOut: far
  75. ELSE
  76.    extrn  _TimeOut: near
  77. ENDIF
  78.  
  79.  
  80. clkdivh    dw  ?       ; actual divisor ... high
  81. clkdivl    dw  ?       ; ... low
  82. clkmod     dw  ?       ; divisor modulus
  83.  
  84. int08      vector  <>
  85.  
  86. appl_ds    dw  ?
  87. old_ss     dw  ?       ; interrupted code's SS
  88. old_sp     dw  ?       ; SP .......
  89.  
  90. soundDelay dw  ?       ; delay counter
  91.  
  92. user_routine_on db (?) ; flag to avoid reentrance
  93.  
  94.  
  95.  
  96.  
  97. ;    clkrate()
  98. ;
  99. ;    change timer-0 divider
  100. ;    IN : AX count divisor
  101.  
  102. clkrate proc
  103.     ; load counter 0 of 8253:
  104.     push    ax
  105.     mov     al, 00110110b   ; square wave mode
  106.     out     43h, al
  107.     pop     ax
  108.     out     40h, al
  109.     xchg    ah, al
  110.     out     40h, al
  111.     xchg    ah, al
  112.     ret
  113. clkrate endp
  114.  
  115.  
  116. ;   _SetInt (state)
  117. ;
  118. ;    enable/disable CPU interrupt.
  119.  
  120. public SetInt
  121.  
  122. SetInt proc
  123.  
  124. Sintframe struc
  125.         dw  (?)
  126.         db  CPSIZE DUP (?)
  127. state    dw    (?)            ; interrupt state
  128. Sintframe ends
  129.     push    bp
  130.     mov     bp, sp
  131.  
  132.     cmp     [bp].state, 0
  133.     jne     s_on
  134.     ; off:
  135.     cli
  136.     jmp     s_end
  137. s_on:
  138.     sti
  139. s_end:
  140.     pop     bp
  141.     ret
  142.  
  143. SetInt endp
  144.  
  145.  
  146.  
  147.  
  148. ;   _SetClkRate (unsigned count)
  149. ;
  150. ;    Initialize interrupt rate to (1.119 MHz / count) cycles/sec.
  151. ;
  152. public _SetClkRate
  153.  
  154. _SetClkRate proc
  155.  
  156. scrframe struc
  157.         dw  (?)
  158.         db  CPSIZE DUP (?)
  159. divid    dw    (?)            ; timer's divider
  160. scrframe ends
  161.     push    bp
  162.     mov     bp, sp
  163.  
  164.     mov     ax, [bp].divid
  165.     pushf
  166.     cli    
  167.     mov     CS:clkdivl, ax
  168.     cmp     ax, 1
  169.     mov     CS:clkdivh, 0
  170.     adc     CS:clkdivh, 0
  171.     call    clkrate
  172.     popf
  173.     pop     bp
  174.     ret
  175. _SetClkRate endp
  176.  
  177.  
  178.  
  179. ; Install clock-driver (soft int-08, timer-0).
  180. ; Save a copy of DS.
  181. ;
  182. public _Clk_install
  183.  
  184. _Clk_install proc
  185.  
  186. ; install clock interrupt handler
  187.     push    ax
  188.     push    dx
  189.  
  190. ; init. clk variables:
  191.     xor     ax, ax
  192.     call    clkrate
  193.     mov     CS:clkdivh, 1
  194.     mov     CS:clkdivl, ax
  195.     mov     CS:clkmod, ax
  196.  
  197. ; init flag:
  198.     mov     cs:user_routine_on, 0
  199.  
  200. ; save application DS:
  201.     mov     ax, ds
  202.     mov     cs:appl_ds, ax
  203.  
  204. ; save current int. vector
  205.     push    es
  206.     mov     ah, 35h
  207.     mov     al, clk_int
  208.     int     21h         ; get old vector
  209.     assume  es:nothing
  210.     mov     CS:int08.regip, bx
  211.     mov     CS:int08.regcs, es
  212.     pop     es
  213. ; install interrupt intercept vector:
  214.     push    ds
  215.     mov     ah, 25h
  216.     mov     al, clk_int
  217.     mov     dx, offset clkint
  218.     mov     bx, CS
  219.     mov     ds, bx
  220.     int     21h         ; set int. vector
  221.     pop     ds
  222.     pop     dx
  223.     pop     ax
  224.  
  225.     ret
  226. _Clk_install endp
  227.  
  228.  
  229.  
  230. ;   _clk_uninstall()
  231. ;
  232. public _Clk_uninstall
  233.  
  234. _Clk_uninstall proc
  235.  
  236.     xor     ax, ax
  237.     call    clkrate
  238. ; reset int. vector:
  239.     push    ds
  240.     mov     ah, 25h
  241.     mov     al, clk_int
  242.     lds     dx, CS:int08
  243.     int     21h         ; set vector ...
  244.     pop     ds
  245.     ret
  246. _Clk_uninstall endp
  247.  
  248.  
  249.  
  250.  
  251. ;   _StartTimeOut (delay)
  252. ;
  253. ;    Initialize count-down delay to 'delay'.
  254. ;
  255.  
  256. public _StartTimeOut
  257.  
  258. _StartTimeOut proc
  259.  
  260. istad    struc
  261.         dw  (?)
  262.         db  CPSIZE DUP (?)
  263. delay    dw    (?)            ; delay before doing the next call
  264. istad    ends
  265.  
  266.     push    bp
  267.     mov     bp, sp
  268.     pushf
  269.     cli
  270.     mov     ax, [bp].delay
  271.     mov     cs:soundDelay, ax
  272.     popf
  273.     pop     bp
  274.     ret
  275.  
  276. _StartTimeOut endp
  277.  
  278.  
  279.  
  280. ;     clkint
  281. ;
  282. ; int-08 Interrupt Driver routine.
  283. ;
  284. ; Check for roll-over of 65536 cycles  (18.2 hz ) and call
  285. ; old driver if so.
  286. ; Count-down delay variable, and if zero, call routine 'TimeOut()'
  287. ; & set the new delay.
  288. ;
  289. clkint  proc
  290.  
  291.     push    ax
  292.  
  293. ; check for roll-over of 65536 cycles  (18.2 hz )
  294.     mov     ax, CS:clkdivl
  295.     add     CS:clkmod, ax
  296.     mov     ax, CS:clkdivh
  297.     adc     ax, 0
  298.     jnz     clkint8
  299. ; not yet time, skip original interrupt
  300.     mov     al, 00100000b
  301.     out     20h, al         ; 8259 ...
  302.     jmp     clkint7
  303. ; do the original interrupt:
  304. clkint8    label    near
  305.     pushf
  306.     call    CS:int08
  307.  
  308. clkint7    label    near
  309.  
  310.     dec     CS:soundDelay       ; 16 bits unsigned counter
  311.     jnz     clkint_end
  312.  
  313. ; to avoid a reentrant call
  314.     cmp     CS:user_routine_on, 0
  315.     jnz     clkint_end      ; already active ...
  316.  
  317. ; end of delay. Prepare environment before calling TimeOut()
  318. ; (allocate temporary stack, set segment registers).
  319. ;
  320.  
  321. ; save all registers...    
  322.     push    bx
  323.     push    cx
  324.     push    dx
  325.     push    ds
  326.     push    es
  327.     push    si
  328.     push    di
  329.     push    bp
  330.  
  331. ; save active stack pointers
  332.     mov     cs:old_ss, ss
  333.     mov     cs:old_sp, sp
  334.  
  335. ; get application's DS
  336.     mov     ax, cs:appl_ds
  337.     mov     es, ax
  338.     mov     ds, ax
  339.  
  340. ; set new stack:
  341.     mov     ss, ax
  342.     mov     sp, offset DGROUP:interrupt_stack_top
  343.  
  344.  
  345. go_user    label near
  346. public go_user
  347.  
  348. ; protect call with flag
  349.     inc     CS:user_routine_on
  350.  
  351. ; call the C routine
  352.     sti
  353.     call    _TimeOut         ; time-out driver ... ==> AX: new delay
  354.  
  355.     cli
  356.     dec     CS:user_routine_on
  357.  
  358. ; compute new delay
  359.     mov     bx, CS:soundDelay
  360.     neg     bx              ; # of interrupt since call to TimeOut()
  361.     cmp     bx, ax              ; time-out ?
  362.     jb      clk_delay_ok            ; no ...
  363.  
  364. ; we must recall TimeOut immediately
  365.     mov     CS:soundDelay, 0
  366.     jmp     go_user
  367.  
  368. clk_delay_ok    label near
  369.     add     CS:soundDelay, ax       ; leftover delay count
  370.  
  371. ; restore stack
  372.     mov     bx, CS:old_ss
  373.     mov     ss, bx
  374.     mov     sp, CS:old_sp
  375.  
  376.     sti
  377.  
  378.     pop     bp
  379.     pop     di
  380.     pop     si
  381.     pop     es
  382.     pop     ds
  383.     pop     dx
  384.     pop     cx
  385.     pop     bx
  386.  
  387. clkint_end    label near
  388.     pop     ax
  389.     iret
  390. clkint    endp
  391.  
  392.     end
  393.