home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / dtx9302 / ctrick / timer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-04  |  7.1 KB  |  237 lines

  1. /* ****************************************************** */
  2. /*                       TIMER.C                          */
  3. /*              (c) 1993 Holger Suhr & DMV                */
  4. /* ****************************************************** */
  5. #include <dos.h>
  6. #include "globals.h"
  7. #include "tmrprot.h"
  8.  
  9. /* ****************************************************** */
  10. /*  da hier die geschwindigkeit des timers aenderbar ist, */
  11. /*  nehmen wir nicht den user-vector sondern den          */
  12. /*  hardware-vector, da ja bei verdoppelter geschwindig-  */
  13. /*  keit die nachfolgenden timer-routinen nur jedes       */
  14. /*  zweite mal aufgerufen werden duerfen.                 */
  15. /* ****************************************************** */
  16.  
  17. #define TIMERVEC    0x08
  18.  
  19. static volatile unsigned int
  20.     dcounter    =0,         /*  down counter           */
  21.     count       =0,         /*  current timer speed    */
  22.     counter     =0;         /*  original timer speed   */
  23.  
  24. static unsigned int
  25.     tmrand      =0,
  26.     tmrshift    =0;
  27.  
  28. /* ****************************************************** */
  29. /* zwei funktionspointer, die bei jedem aktuellen         */
  30. /* timer-tick aufgerufen werden (unabhaengig von der      */
  31. /* timer-geschindigkeit)                                  */
  32. /* ****************************************************** */
  33.  
  34. static void (*afuncs[2])(unsigned);
  35.  
  36. /* ****************************************************** */
  37. /*  zwei funktionspointer die bei jedem original          */
  38. /*  timer-tick aufgerufen werden (immer bezogen auf       */
  39. /*  original-geschindigkeit)                              */
  40. /* ****************************************************** */
  41.  
  42. static void (*ofuncs[2])(unsigned);
  43.  
  44. static void interrupt (*oldtimer)(void );
  45. static void interrupt timer_isr(void );
  46.  
  47.  
  48. /* ****************************************************** */
  49. /*  setzen der timer-tick geschwindigkeit                 */
  50. /*                                                        */
  51. /*  fact 0 entspricht originalgeschwindigkeit ca. 18.2/s  */
  52. /*  aus geschwindigkeitsgruenden nur 2-er potenzen        */
  53. /*  erlaubt werte 0-7 werden zum shiften verwendet, d.h.  */
  54. /*  der timer kann faktor 1,2,4,8,16,32,64,128 laufen     */
  55. /* ****************************************************** */
  56.  
  57. tmr_factor(unsigned fact)
  58. {
  59.   unsigned divi;
  60.  
  61.   if (fact < 0 || fact > 7) return(-1);
  62.  
  63.   if (!fact) divi = tmrand = 0;
  64.   else {
  65.  
  66.     /*  errechnen einer AND-Maske fuer den schnellen test,
  67.         ob die bisherige timer-interrupt-funktion aufgerufen
  68.         werden muss (damit die uhr weiterhin richtig geht)
  69.     */
  70.  
  71.     tmrand = (1 << fact) - 1;
  72.     divi   = (unsigned) 32768 >> fact;
  73.   }
  74.  
  75.   /* setzen des timer bausteins */
  76.  
  77.   disable();
  78.   outportb(0x43, 0x36);                  /*  00110110    */
  79.   outportb(0x40,divi&0xff);
  80.   outportb(0x40,(divi>>8)&0xff);
  81.   enable();
  82.  
  83.   tmrshift = fact;
  84.  
  85.   return(0);
  86. }
  87.  
  88. /* ****************************************************** */
  89. /*  liefern der derzeitigen timergeschwindigkeit          */
  90. /******************************************************** */
  91.  
  92. unsigned tmr_getfact(void )
  93. {
  94.   return(tmrshift);
  95. }
  96.  
  97. /* ****************************************************** */
  98. /*  initialisieren der timer-funktionen                   */
  99. /*  mit angabe der geschwindigkeit (siehe tmr_factor)     */
  100. /* ****************************************************** */
  101.  
  102. tmr_init(unsigned fact)
  103. {
  104.   int i = tmr_factor(fact);
  105.  
  106.   if (i) return(i);
  107.  
  108.   /*  sind wir bereits installiert ??
  109.       timerinstalled liegt in globals.h damit andere sourcen
  110.       wissen, ob diese funktionen installiert sind, ohne sie
  111.       dadurch bereits zu linken
  112.   */
  113.  
  114.   if (!timerinstalled) {
  115.     oldtimer = getvect(TIMERVEC);
  116.     setvect(TIMERVEC, timer_isr);
  117.     atexit(tmr_rest);
  118.   }
  119.  
  120.   timerinstalled = 1;
  121.  
  122.   return(0);
  123. }
  124.  
  125. /* ****************************************************** */
  126. /* uns deinstallieren und timer auf original-speed setzen */
  127. /* ****************************************************** */
  128.  
  129. void tmr_rest(void)
  130. {
  131.   tmr_factor(0);
  132.  
  133.   if (timerinstalled)
  134.     setvect(TIMERVEC, oldtimer);
  135.  
  136.   timerinstalled = 0;
  137. }
  138.  
  139. /* ****************************************************** */
  140. /*  erzeugen eines delays von tics timer-ticks gemessen   */
  141. /*  zur AKTUELLEN geschwindigkeit                         */
  142. /* ****************************************************** */
  143.  
  144. void tmr_delay(unsigned tics)
  145. {
  146.   if (timerinstalled)
  147.     for (dcounter = tics; dcounter; );
  148. }
  149.  
  150. /* ****************************************************** */
  151. /*  tick-counter zur AKTUELLEN geschwindigkeit            */
  152. /* ****************************************************** */
  153.  
  154. unsigned int tmr_acttics(void)
  155. {
  156.   return(count);
  157. }
  158.  
  159. /* ****************************************************** */
  160. /* liefern des tick-counters zur ORIGINAL geschwindigkeit */
  161. /* ****************************************************** */
  162.  
  163. unsigned int tmr_normtics(void)
  164. {
  165.   return(counter);
  166. }
  167.  
  168. /* ****************************************************** */
  169. /*  definieren einer bei jedem timer tick aufzurufenden   */
  170. /*  funktion                                              */
  171. /*  das installieren von funktionen ist fuer andere       */
  172. /*  library-funktionen gedacht (z.B. alarm,timeout) und   */
  173. /*  daher mit wenig tests bedacht.                        */
  174. /*  id bestimmt den slot (0-1) (natuerlich leicht         */
  175. /*  erweiterbar). art bestimmt ob jeder tic zur aktuellen */
  176. /*  oder zur originalgeschwindigkeit den call verursachen */
  177. /*  soll (1=original).                                    */
  178. /* ****************************************************** */
  179.  
  180. tmr_intfunc(void (*func)(unsigned),int id,int art)
  181. {
  182.   void (**P)(unsigned);
  183.  
  184.   P = (art) ? ofuncs:afuncs;
  185.  
  186.   if (id != !!id) return(-1);
  187.  
  188.   P[id] = func;
  189.  
  190.   return(0);
  191. }
  192.  
  193. /* ****************************************************** */
  194. /*  die interrupt-funktion die vom HARDWARE Interrupt     */
  195. /*  aufgerufen wird                                       */
  196. /* ****************************************************** */
  197.  
  198. static void interrupt timer_isr(void)
  199. {
  200.   count++;
  201.  
  202.   /* wenn down-counter vorhanden, dann runterzaehlen      */
  203.  
  204.   if (dcounter) dcounter--;
  205.  
  206.     /* aufzurufende funktionen zur aktuellen
  207.        geschwindigkeit ?           */
  208.  
  209.     if(afuncs[0]) (*afuncs[0])(count);
  210.     if(afuncs[1]) (*afuncs[1])(count);
  211.  
  212.     /*  ist dieser interrupt zur aktuellen geschwindigkeit
  213.        ein ganzes vielfaches zur original-geschwindigkeit ?
  214.       dann muessen wir an alle denken, die 18.2/sek erwarten
  215.     */
  216.  
  217.     if (!(count&tmrand)) {
  218.       counter++;
  219.  
  220.       if(ofuncs[0]) (*ofuncs[0])(counter);
  221.       if(ofuncs[1]) (*ofuncs[1])(counter);
  222.  
  223.       /*  und jetzt rufen wir alle die auf, die sich
  224.          ordnungsgemaess in einen timer-interrupt
  225.          installiert haben              */
  226.  
  227.       (*oldtimer)();
  228.     }
  229.  
  230.     /* EOI */
  231.  
  232.     outportb(0x20,0x20);
  233. }
  234. /* ****************************************************** */
  235. /*                 Ende von TIMER.C                       */
  236.  
  237.