home *** CD-ROM | disk | FTP | other *** search
- /* ****************************************************** */
- /* TIMER.C */
- /* (c) 1993 Holger Suhr & DMV */
- /* ****************************************************** */
- #include <dos.h>
- #include "globals.h"
- #include "tmrprot.h"
-
- /* ****************************************************** */
- /* da hier die geschwindigkeit des timers aenderbar ist, */
- /* nehmen wir nicht den user-vector sondern den */
- /* hardware-vector, da ja bei verdoppelter geschwindig- */
- /* keit die nachfolgenden timer-routinen nur jedes */
- /* zweite mal aufgerufen werden duerfen. */
- /* ****************************************************** */
-
- #define TIMERVEC 0x08
-
- static volatile unsigned int
- dcounter =0, /* down counter */
- count =0, /* current timer speed */
- counter =0; /* original timer speed */
-
- static unsigned int
- tmrand =0,
- tmrshift =0;
-
- /* ****************************************************** */
- /* zwei funktionspointer, die bei jedem aktuellen */
- /* timer-tick aufgerufen werden (unabhaengig von der */
- /* timer-geschindigkeit) */
- /* ****************************************************** */
-
- static void (*afuncs[2])(unsigned);
-
- /* ****************************************************** */
- /* zwei funktionspointer die bei jedem original */
- /* timer-tick aufgerufen werden (immer bezogen auf */
- /* original-geschindigkeit) */
- /* ****************************************************** */
-
- static void (*ofuncs[2])(unsigned);
-
- static void interrupt (*oldtimer)(void );
- static void interrupt timer_isr(void );
-
-
- /* ****************************************************** */
- /* setzen der timer-tick geschwindigkeit */
- /* */
- /* fact 0 entspricht originalgeschwindigkeit ca. 18.2/s */
- /* aus geschwindigkeitsgruenden nur 2-er potenzen */
- /* erlaubt werte 0-7 werden zum shiften verwendet, d.h. */
- /* der timer kann faktor 1,2,4,8,16,32,64,128 laufen */
- /* ****************************************************** */
-
- tmr_factor(unsigned fact)
- {
- unsigned divi;
-
- if (fact < 0 || fact > 7) return(-1);
-
- if (!fact) divi = tmrand = 0;
- else {
-
- /* errechnen einer AND-Maske fuer den schnellen test,
- ob die bisherige timer-interrupt-funktion aufgerufen
- werden muss (damit die uhr weiterhin richtig geht)
- */
-
- tmrand = (1 << fact) - 1;
- divi = (unsigned) 32768 >> fact;
- }
-
- /* setzen des timer bausteins */
-
- disable();
- outportb(0x43, 0x36); /* 00110110 */
- outportb(0x40,divi&0xff);
- outportb(0x40,(divi>>8)&0xff);
- enable();
-
- tmrshift = fact;
-
- return(0);
- }
-
- /* ****************************************************** */
- /* liefern der derzeitigen timergeschwindigkeit */
- /******************************************************** */
-
- unsigned tmr_getfact(void )
- {
- return(tmrshift);
- }
-
- /* ****************************************************** */
- /* initialisieren der timer-funktionen */
- /* mit angabe der geschwindigkeit (siehe tmr_factor) */
- /* ****************************************************** */
-
- tmr_init(unsigned fact)
- {
- int i = tmr_factor(fact);
-
- if (i) return(i);
-
- /* sind wir bereits installiert ??
- timerinstalled liegt in globals.h damit andere sourcen
- wissen, ob diese funktionen installiert sind, ohne sie
- dadurch bereits zu linken
- */
-
- if (!timerinstalled) {
- oldtimer = getvect(TIMERVEC);
- setvect(TIMERVEC, timer_isr);
- atexit(tmr_rest);
- }
-
- timerinstalled = 1;
-
- return(0);
- }
-
- /* ****************************************************** */
- /* uns deinstallieren und timer auf original-speed setzen */
- /* ****************************************************** */
-
- void tmr_rest(void)
- {
- tmr_factor(0);
-
- if (timerinstalled)
- setvect(TIMERVEC, oldtimer);
-
- timerinstalled = 0;
- }
-
- /* ****************************************************** */
- /* erzeugen eines delays von tics timer-ticks gemessen */
- /* zur AKTUELLEN geschwindigkeit */
- /* ****************************************************** */
-
- void tmr_delay(unsigned tics)
- {
- if (timerinstalled)
- for (dcounter = tics; dcounter; );
- }
-
- /* ****************************************************** */
- /* tick-counter zur AKTUELLEN geschwindigkeit */
- /* ****************************************************** */
-
- unsigned int tmr_acttics(void)
- {
- return(count);
- }
-
- /* ****************************************************** */
- /* liefern des tick-counters zur ORIGINAL geschwindigkeit */
- /* ****************************************************** */
-
- unsigned int tmr_normtics(void)
- {
- return(counter);
- }
-
- /* ****************************************************** */
- /* definieren einer bei jedem timer tick aufzurufenden */
- /* funktion */
- /* das installieren von funktionen ist fuer andere */
- /* library-funktionen gedacht (z.B. alarm,timeout) und */
- /* daher mit wenig tests bedacht. */
- /* id bestimmt den slot (0-1) (natuerlich leicht */
- /* erweiterbar). art bestimmt ob jeder tic zur aktuellen */
- /* oder zur originalgeschwindigkeit den call verursachen */
- /* soll (1=original). */
- /* ****************************************************** */
-
- tmr_intfunc(void (*func)(unsigned),int id,int art)
- {
- void (**P)(unsigned);
-
- P = (art) ? ofuncs:afuncs;
-
- if (id != !!id) return(-1);
-
- P[id] = func;
-
- return(0);
- }
-
- /* ****************************************************** */
- /* die interrupt-funktion die vom HARDWARE Interrupt */
- /* aufgerufen wird */
- /* ****************************************************** */
-
- static void interrupt timer_isr(void)
- {
- count++;
-
- /* wenn down-counter vorhanden, dann runterzaehlen */
-
- if (dcounter) dcounter--;
-
- /* aufzurufende funktionen zur aktuellen
- geschwindigkeit ? */
-
- if(afuncs[0]) (*afuncs[0])(count);
- if(afuncs[1]) (*afuncs[1])(count);
-
- /* ist dieser interrupt zur aktuellen geschwindigkeit
- ein ganzes vielfaches zur original-geschwindigkeit ?
- dann muessen wir an alle denken, die 18.2/sek erwarten
- */
-
- if (!(count&tmrand)) {
- counter++;
-
- if(ofuncs[0]) (*ofuncs[0])(counter);
- if(ofuncs[1]) (*ofuncs[1])(counter);
-
- /* und jetzt rufen wir alle die auf, die sich
- ordnungsgemaess in einen timer-interrupt
- installiert haben */
-
- (*oldtimer)();
- }
-
- /* EOI */
-
- outportb(0x20,0x20);
- }
- /* ****************************************************** */
- /* Ende von TIMER.C */
-
-