10 #define TIMER_QUANTUM 100
11 #define TIMER_FREQ 1024 //Hz
12 #define MS_PER_TICK_WHOLE (1000/(TIMER_FREQ))
13 #define MS_PER_TICK_FRACT ((Uint64)(1000*TIMER_FREQ-((Uint64)MS_PER_TICK_WHOLE)*0x80000000/TIMER_FREQ))
16 typedef struct sTimer {
18 void (*Callback)(void*);
23 void Time_Interrupt();
24 void Timer_CallTimers();
28 Sint64 giTimestamp = 0;
29 Uint64 giPartMiliseconds = 0;
30 tTimer gTimers[NUM_TIMERS];
34 * \fn int Time_Setup()
35 * \brief Sets the system time from the Realtime-Clock
41 outb(0x70, inb(0x70)&0x7F); // Disable NMIs
42 __asm__ __volatile__ ("cli"); // Disable normal interrupts
45 outb(0x70, 0x0B); // Set the index to register B
46 val = inb(0x71); // Read the current value of register B
47 outb(0x70, 0x0B); // Set the index again (a read will reset the index to register D)
48 outb(0x71, val | 0x40); // Write the previous value or'd with 0x40. This turns on bit 6 of register D
50 __asm__ __volatile__ ("sti"); // Disable normal interrupts
51 outb(0x70, inb(0x70)|0x80); // Disable NMIs
53 // Install IRQ Handler
54 IRQ_AddHandler(8, Time_Interrupt);
59 * \fn void Time_Interrupt()
60 * \brief Called on the timekeeping IRQ
65 giTimestamp += MS_PER_TICK_WHOLE;
66 giPartMiliseconds += MS_PER_TICK_FRACT;
67 if(giPartMiliseconds > 0x80000000) {
69 giPartMiliseconds -= 0x80000000;
72 //Log("giTimestamp = %lli", giTimestamp);
76 // Make sure the RTC Fires again
77 outb(0x70, 0x0C); // Select register C
78 inb(0x71); // Just throw away contents.
82 * \fn void Time_TimerThread()
85 void Time_TimerThread()
88 Threads_SetName("TIMER");
90 next = giTimestamp + TIMER_QUANTUM;
93 while(giTimestamp < next) Threads_Yield();
94 next = giTimestamp + TIMER_QUANTUM;
102 * \brief Return the current timestamp
110 * \fn void Timer_CallTimers()
112 void Timer_CallTimers()
115 void (*callback)(void *);
121 //Log("Timer %i", i);
122 if(gTimers[i].Callback == NULL) continue;
123 Log("%i - %lli < %lli", i, giTimestamp, gTimers[i].FiresAfter);
124 if(giTimestamp < gTimers[i].FiresAfter) continue;
125 callback = gTimers[i].Callback;
126 gTimers[i].Callback = NULL;
127 callback(gTimers[i].Argument);
132 * \fn int Time_CreateTimer(int Delta, void *Callback, void *Argument)
134 int Time_CreateTimer(int Delta, void *Callback, void *Argument)
138 if(Callback == NULL) return -1;
144 if(gTimers[ret].Callback != NULL) continue;
145 gTimers[ret].Callback = Callback;
146 gTimers[ret].FiresAfter = giTimestamp + Delta;
147 gTimers[ret].Argument = Argument;
148 Log("Callback = %p", Callback);
149 Log("Timer %i fires at %lli", ret, gTimers[ret].FiresAfter);
156 * \fn void Time_RemoveTimer(int ID)
158 void Time_RemoveTimer(int ID)
160 if(ID < 0 || ID >= NUM_TIMERS) return;
161 gTimers[ID].Callback = NULL;
165 * \fn void Time_Delay(int Delay)
166 * \brief Delay for a small ammount of time
168 void Time_Delay(int Delay)
170 Sint64 dest = giTimestamp + Delay;
171 while(dest < giTimestamp) Threads_Yield();