home *** CD-ROM | disk | FTP | other *** search
/ Chestnut's Multimedia Mania / MM_MANIA.ISO / midi / cmtcmu / timdif.asm < prev    next >
Assembly Source File  |  1990-06-28  |  14KB  |  417 lines

  1. ;version 1 released 6-10-86 
  2.     title timdif - real time at different than clock rate 
  3. debug=-1 ;set to -1 to turn on debugging code 
  4. ;written by Aaron Wohl 
  5. ;       for Roger Dannerberg 
  6. ;        at The Center for the Arts and technolagy 
  7. ;           Carnegie Mellon University 
  8. ;        5000 Forbes Ave 
  9. ;        Pittsburgh, PA 15xxx 
  10. ;change log: 
  11. ; Jun 10 86 avw      - release version 1 
  12. ; Jun 04 86 avw      - create from wohl's personal timer.asm 
  13. ;this module provides a 32bit timer that counts at a rate different than 
  14. ;the ~54ms time provided by the bios.  It is currently configured to 
  15. ;count in 10ms tics. 
  16. ;The idea is to do subtractions and keep a remainder instead of dividing 
  17. ;the bios and timer chip time to save divide or multiply instructions. 
  18. ;This is probably only a good idea if the rate you want is near the 
  19. ;bios rate. 
  20. ;things to do: 
  21. ; change dodiv to be alot smarter and faster.  it currently loops 
  22. ; subtracting divr from rem, instead subtract 3*divr and see if there 
  23. ; is a borrow and go from there.  this will decrease the maximum divide time. 
  24.   
  25. ;************************************************************************ 
  26. ;*                                    * 
  27. ;*    Module interface specifications                    * 
  28. ;*                                    * 
  29. ;************************************************************************ 
  30. ; ibm_time - this routine is the reason this module exists, it returns the 
  31. ;       current time in 10ms tics. 
  32. ;     note:ibm_time() may not be called with interupts disabled 
  33. ;usage: unsigned long i,ibm_time(); i=ibm_time(); 
  34. ; cletime - stop our timer.  crash the system if timer not currently running. 
  35. ;usage: cletime(); 
  36. ; settime - zero our timer and start counting.  crash the system if our timer 
  37. ;       is already running. 
  38. ;       if debbuging, also zero the value gettic() returns (see gettic) 
  39. ;usage: settime(); 
  40. ; overall usage: 
  41. ;  a) call settime() to start the timer 
  42. ;  b) call ibm_time() as many times as you like to get the time. 
  43. ;  c) call cletime() to stop timing 
  44. ;  d) exit the program, or if you like, goto step a) 
  45.   
  46. ;************************************************************************ 
  47. ;*                                    * 
  48. ;*    Module debug interface specifications                * 
  49. ;*                                    * 
  50. ;************************************************************************ 
  51. ; gettic - return high precision (8253 counter 0) reading from when 
  52. ;       the latest interupt happened.  latest meaning the most late, the 
  53. ;       interupt delayed for the longest time. usefull for debugging to see 
  54. ;       if someone is leaving the interups off for too long. 
  55. ;     note:we must be called with debug on for gettic to function, always 
  56. ;       returns zero otherwise 
  57. ; usage: int i,getic(); i=gettic(); 
  58. ; getbtim - return the 32bit bios time (it counts in ~54ms tics). 
  59. ;        usefull for debugging.  since the rest of this module runs 
  60. ;        off the same clock, this time (when converted to 10ms ticks) 
  61. ;        should never be more then 6 (10ms) ticks different. 
  62. ;usage: unsigned long i,getbtim(); i=getbtim(); 
  63.   
  64. ;************************************************************************ 
  65. ;*                                    * 
  66. ;*    Timeing constants, linkages, libraries                * 
  67. ;*                                    * 
  68. ;************************************************************************ 
  69.  
  70. divr    equ 3054545        ;divider for 11931.81667 to get 10ms 
  71. divlow    equ 09bd1h        ;low word of divr 
  72. divhig    equ 0002eh        ;high word of divr 
  73.  
  74.     include macsym.lib    ;control constructs 
  75.     include prcsym.lib    ;procedure data declarators 
  76.     cmods_            ;set linkage mode to c small model 
  77.  
  78.   
  79. ;************************************************************************ 
  80. ;*                                    * 
  81. ;*    data global to timdif                        * 
  82. ;*                                    * 
  83. ;************************************************************************ 
  84.  
  85. ;define memory location of timer interupt vector 
  86. ivec    segment at 0 
  87.     org    8h*4 
  88. timvec    label word 
  89. ivec    ends 
  90.  
  91.     dseg timdat 
  92.     if debug 
  93. tictim    dw 0            ;remeber when ticks happen 
  94.     endif 
  95.  
  96. ;remainder from previous divisions as a 32 bit number low byte to high byte 
  97. ;also, used to remember part of current second already used 
  98. rem    label dword 
  99. rem0w    label word        ;a few names for things since we 
  100. rem0b    db 0            ; sometimes do byte operations and sometimes 
  101. rem1w    label word        ; do word operations 
  102. rem1b    db 0 
  103. rem2w    label word 
  104. rem2b    db 0 
  105. rem3b    db 0 
  106.  
  107. now    label dword            ;current time in our units 
  108. now0w    dw 0                ;for returning result to user 
  109. now2w    dw 0 
  110.     endds 
  111.  
  112.   
  113.     pseg prog 
  114. ;************************************************************************ 
  115. ;*                                    * 
  116. ;*    dodiv - divide bx(low word) ax(high word)            * 
  117. ;*        by tivr                            * 
  118. ;*        result in cx, remainder in ax,bx 
  119. ;*                                    * 
  120. ;*                                    * 
  121. ;************************************************************************ 
  122.  
  123. ;do divide 
  124. dodiv    proc near 
  125.     mov cx,0        ;initilize result of division 
  126.     do_ 
  127.      inc cx            ;divide happend one more time 
  128.      sub bx,divlow 
  129.      sbb ax,divhig 
  130.      jnc top_        ;loop till we borrow 
  131.     od_ 
  132.     dec cx            ;correct for going once to many times 
  133.     add bx,divlow        ;undo last subtract 
  134.     adc ax,divhig 
  135.     ret 
  136. dodiv    endp 
  137.   
  138. ;************************************************************************ 
  139. ;*                                    * 
  140. ;*    Timer routine to piggy back on bios timer interupt        * 
  141. ;*    data addressed by cs for interupt routine            * 
  142. ;*                                    * 
  143. ;************************************************************************ 
  144.  
  145. romwd    label word        ;word address of rom tim 
  146. romtim    dd ?            ;rom timer interupt address 
  147. timds    dw ?            ;data segment for timer routines 
  148.   
  149. ;************************************************************************ 
  150. ;*                                    * 
  151. ;*    Macro to read time into ax                    * 
  152. ;*    This is not a routine to save the subroutine call overhead    * 
  153. ;*                                    * 
  154. ;************************************************************************ 
  155. timprt    equ 040h        ;timer 0 port 
  156. timcmd    equ (timprt+3)        ;timer control port 
  157. latcmd    equ 000h        ;command to latch a time, timer 0 
  158. modcmd    equ 034h        ;set to mode 2 instead of mode 3 
  159.   
  160. ;************************************************************************ 
  161. ;*                                    * 
  162. ;*    Routine to return to user, when the latest timer tick happened    * 
  163. ;*                                    * 
  164. ;************************************************************************ 
  165.     public gettic 
  166.     prcent gettic 
  167.     if debug 
  168.       mov ax,tictim 
  169.     else 
  170.       xor ax,ax 
  171.     endif 
  172.     prcexi gettic        ;return the tic time to lattice c 
  173.   
  174. ;************************************************************************ 
  175. ;*                                    * 
  176. ;*    Routine for returning the current bios time            * 
  177. ;*    getbtim - return a 32bit time in our bios tics            * 
  178. ;*    only used to check our accuracy                    * 
  179. ;*                                    * 
  180. ;************************************************************************ 
  181.     public getbtim 
  182.     prcent getbtim,,,<,ds> 
  183.     mov ax,040h        ;address of rom data 
  184.     mov ds,ax 
  185.     cli 
  186.     mov bx,ds:[06ch]    ;get high and low words of the time 
  187.     mov ax,ds:[06eh] 
  188.     sti 
  189.     prcexi getbtim        ;return the time to lattice c 
  190.   
  191. ;read a latched time into cx cl=low, cx=high 
  192. REDTIM    macro 
  193.     mov al,latcmd        ;latch a timer 
  194.     out timcmd,al        ;send command to 8153 
  195.     in al,timprt        ;get low byte of time 
  196.     mov cl,al        ;save it 
  197.     in al,timprt        ;get high byte of the time 
  198.     mov ch,al 
  199.     neg cx 
  200.     endm 
  201.  
  202.   
  203. ;************************************************************************ 
  204. ;*                                    * 
  205. ;*    Routine for returning the current time                * 
  206. ;*    ibm_time - return a 32bit time in our units            * 
  207. ;*                                    * 
  208. ;************************************************************************ 
  209.     public ibm_time 
  210.     prcent ibm_time 
  211.  
  212.     do_ 
  213.      push es        ;free up es to point to 
  214.      mov ax,040h        ;address of rom data 
  215.      mov es,ax 
  216.      cli 
  217.      REDTIM            ;read timer into ax 
  218.      sti            ;do next instruction, then ints on 
  219.      mov bx,es:[06ch]    ;(interupts off here, see sti def) get time 
  220.      cli 
  221.      cmp bx,es:[06ch]    ;time change? set z flag if ok 
  222.      pop es 
  223.      jnz top_        ;if time changed then counter is wrong 
  224.     od_ 
  225. ;note: interupts are off when exiting the loop! so that now doesn't 
  226. ;      get bashed on by the timer interupt code while we are updating it 
  227. ;note: the 8253 timer counts down, so ax has the negative of the part of 
  228. ;      the tick 
  229.     mov bx,rem0w        ;get low word of remainder 
  230.     mov ax,rem2w        ;get high word 
  231.     add bh,cl 
  232.     adc al,ch 
  233.     adc ah,0 
  234.  
  235.     call dodiv        ;fixup now to be correct 
  236.  
  237.     add cx,now0w        ;get now plus part of tick 
  238.     mov ax,0 
  239.     adc ax,now2w 
  240.     sti            ;done, allow interupts now 
  241.     mov bx,cx        ;put low bits where lattice c wants them 
  242.     prcexi ibm_time         ;return bx,ax (current time) 
  243.   
  244. ;************************************************************************ 
  245. ;*                                    * 
  246. ;*    Routine for stopping our timer                    * 
  247. ;*    cletime - stop timer remove patch into bios timer        * 
  248. ;*                                    * 
  249. ;************************************************************************ 
  250.  
  251. ;clear the timer interupt routine 
  252.     public cletime 
  253.     prcent cletime,,,<,ds> 
  254.     assume ds:ivec        ;address current vectors 
  255.     mov ax,ivec 
  256.     mov ds,ax 
  257.      
  258.     cli 
  259.     mov ax,romwd 
  260.     mov timvec,ax        ;restore original interupt vector 
  261.     mov ax,romwd[2] 
  262.     mov timvec[2],ax 
  263.     sti 
  264.      
  265.     assume ds:dgroup 
  266.     prcexi cletime 
  267.  ;************************************************************************ 
  268. ;*                                    * 
  269. ;*    Routine for starting our timer                    * 
  270. ;*    settime - zero now (time starts from zero), also patch into    * 
  271. ;*         bios timer interupt so we can call timint on each    * 
  272. ;*         timer tick                        * 
  273. ;*                                    * 
  274. ;************************************************************************ 
  275.  
  276.     public settime 
  277.     prcent settime,,,<,ds> 
  278.  
  279.     xor ax,ax        ;get a zero 
  280.     if debug 
  281.      mov tictim,ax        ;clear latest tick time 
  282.     endif 
  283.     mov now0w,ax        ;clear now 
  284.     mov now2w,ax 
  285.     mov rem0w,ax        ;clear remainder 
  286.         mov rem2w,ax 
  287.  
  288. ;change the timer to mode 2 (rate generator ) so we can see what part of the 
  289. ;current tick we are in.  the rom sets it to mode 3 (square wave).  mode 3 
  290. ;counts by two then twidiles the counter output line.  thus if read the 
  291. ;timer you can't tell which half of the tick you are in.  mode 2 counts 
  292. ;by one then gives a one clock pulse tick, which is just fine with 
  293. ;the 8259 interupt controller chip. 
  294.     mov al,034h        ;set timer mode 
  295.     cli            ;lets not mess with the time interupt routine 
  296.     out timcmd,al 
  297.     xor al,al        ;something to send to timer for time 
  298.     out timprt,al        ;after setting mode need to send a time 
  299.     out timprt,al        ;to restart the timer 
  300.     sti 
  301.  
  302.     mov ax,ds        ;save stack segment 
  303.     mov timds,ax 
  304.  
  305.     assume ds:ivec        ;address current vectors 
  306.     mov ax,ivec 
  307.     mov ds,ax 
  308.      
  309.     mov ax,timvec        ;save original interupt vector 
  310.     mov romwd,ax 
  311.     mov ax,timvec[2] 
  312.     mov romwd[2],ax 
  313.  
  314.     mov ax,cs        ;get new code segment 
  315.     mov bx,offset timint    ;code routine 
  316.     cli 
  317.     mov timvec,bx        ;set new timer offset 
  318.     mov timvec[2],ax    ;set new timer segment 
  319.     sti 
  320.  
  321.     assume ds:dgroup 
  322.     prcexi settime 
  323.   
  324. ;************************************************************************ 
  325. ;*                                    * 
  326. ;*    More timer routine to piggy back on bios timer interupt        * 
  327. ;*    This page has the code that gets called by the hardware        * 
  328. ;*    Instead of the bios code                    * 
  329. ;*    It saves AX,BX,CX,DS then falls into the next page of code    * 
  330. ;*    on the users stack.                        * 
  331. ;*                                    * 
  332. ;************************************************************************ 
  333.  
  334. ;new timer interupt 
  335.     public timint;for debugging only 
  336. timint    proc far 
  337.     assume ds:nothing,es:nothing,ss:nothing    ;we know nothing, nothing 
  338. ;note: it is safe to use 5 stack levels in a timer routine since the 
  339. ;      bios interupt we replace does.  (save 4 regs, allowing one stack 
  340. ;      level left for the call to dodiv) 
  341.     push ax 
  342.     push bx 
  343.     push cx 
  344.     push ds 
  345.     mov ax,timds        ;set new ss and sp 
  346.     mov ds,ax        ;set ds for user routine 
  347.     assume ds:dgroup,ss:dgroup 
  348.   
  349. ;************************************************************************ 
  350. ;*                                    * 
  351. ;*    More timer routine to piggy back on bios timer interupt        * 
  352. ;*    We take care of keeping our time up to date            * 
  353. ;*                                    * 
  354. ;*    Debugging code, remember what part of a tick interupts happen    * 
  355. ;*                                    * 
  356. ;************************************************************************ 
  357.     if debug 
  358.       REDTIM        ;see when it is 
  359.       cmp tictim,cx        ;later than before? 
  360.       ifskp_ nc        ;remember time if yes 
  361.        mov tictim,cx    ;remember it 
  362.       endif_ 
  363.     endif 
  364.   
  365. ;************************************************************************ 
  366. ;*                                    * 
  367. ;*    More timer routine to piggy back on bios timer interupt        * 
  368. ;*    We take care of keeping our time up to date            * 
  369. ;*                                    * 
  370. ;************************************************************************ 
  371.  
  372. ;get number to divide 
  373.     mov bx,rem0w        ;get low word of remainder 
  374.     mov ax,rem2w        ;get high word 
  375.     inc ah            ;one more tick has passed 
  376.  
  377.     call dodiv        ;update now accordingly 
  378.  
  379. ;put back current remainder 
  380.     mov rem0w,bx 
  381.     mov rem2w,ax 
  382.  
  383. ;add result into now 
  384.     add now0w,cx        ;move the time forward 
  385.     ifskp_ nc        ;carry out of low word? 
  386.      inc now2w        ;had a carry, propagate it 
  387.     endif_ 
  388.   
  389. ;************************************************************************ 
  390. ;*                                    * 
  391. ;*    NOTE: execution runs into this page from above (save call/ret)    * 
  392. ;*    More timer routine to piggy back on bios timer interupt        * 
  393. ;*    This page restores AX,BX,CX,DS,SS,SP then jumps to the normal    * 
  394. ;*    bios code.                            * 
  395. ;*                                    * 
  396. ;************************************************************************ 
  397.  
  398.     assume ds:nothing,ss:nothing 
  399.     pop ds 
  400.     pop cx 
  401.     pop bx 
  402.     pop ax 
  403.     jmp romtim 
  404. timint    endp 
  405.  
  406.     endps 
  407.     end 
  408.