10 #define TIMER_QUANTUM 100
11 // 2^(15-rate), 15: 1HZ, 5: 1024Hz, 2: 8192Hz
12 #define TIMER_RATE 12 // (Max: 15, Min: 2) - 15 = 1Hz, 13 = 4Hz, 12 = 8Hz, 11 = 16Hz 10 = 32Hz, 2
13 #define TIMER_FREQ (0x8000>>TIMER_RATE) //Hz
14 #define MS_PER_TICK_WHOLE (1000/(TIMER_FREQ))
15 #define MS_PER_TICK_FRACT ((Uint64)(1000*TIMER_FREQ-((Uint64)MS_PER_TICK_WHOLE)*0x80000000/TIMER_FREQ))
18 typedef struct sTimer {
20 void (*Callback)(void*);
25 void Time_Interrupt();
26 void Timer_CallTimers();
30 Sint64 giTimestamp = 0;
31 Uint64 giPartMiliseconds = 0;
32 tTimer gTimers[NUM_TIMERS];
36 * \fn int Time_Setup()
37 * \brief Sets the system time from the Realtime-Clock
43 outb(0x70, inb(0x70)&0x7F); // Disable NMIs
44 __asm__ __volatile__ ("cli"); // Disable normal interrupts
46 // Set IRQ8 firing rate
47 outb(0x70, 0x0A); // Set the index to register A
48 val = inb(0x71); // Get the current value of register A
49 outb(0x70, 0x0A); // Reset index to A
52 outb(0x71, val); // Update the timer rate
55 outb(0x70, 0x0B); // Set the index to register B
56 val = inb(0x71); // Read the current value of register B
57 outb(0x70, 0x0B); // Set the index again (a read will reset the index to register D)
58 outb(0x71, val | 0x40); // Write the previous value or'd with 0x40. This turns on bit 6 of register D
60 __asm__ __volatile__ ("sti"); // Disable normal interrupts
61 outb(0x70, inb(0x70)|0x80); // Disable NMIs
63 // Install IRQ Handler
64 IRQ_AddHandler(8, Time_Interrupt);
69 * \fn void Time_Interrupt()
70 * \brief Called on the timekeeping IRQ
75 giTimestamp += MS_PER_TICK_WHOLE;
76 giPartMiliseconds += MS_PER_TICK_FRACT;
77 if(giPartMiliseconds > 0x80000000) {
79 giPartMiliseconds -= 0x80000000;
82 //Log("giTimestamp = %lli", giTimestamp);
86 // Make sure the RTC Fires again
87 outb(0x70, 0x0C); // Select register C
88 inb(0x71); // Just throw away contents.
93 * \fn void Time_TimerThread()
95 void Time_TimerThread()
98 Threads_SetName("TIMER");
100 next = giTimestamp + TIMER_QUANTUM;
103 while(giTimestamp < next) Threads_Yield();
104 next = giTimestamp + TIMER_QUANTUM;
112 * \brief Return the current timestamp
120 * \fn void Timer_CallTimers()
122 void Timer_CallTimers()
125 void (*callback)(void *);
131 if(gTimers[i].Callback == NULL) continue;
132 if(giTimestamp < gTimers[i].FiresAfter) continue;
133 callback = gTimers[i].Callback;
134 gTimers[i].Callback = NULL;
135 callback(gTimers[i].Argument);
140 * \fn int Time_CreateTimer(int Delta, void *Callback, void *Argument)
142 int Time_CreateTimer(int Delta, void *Callback, void *Argument)
146 if(Callback == NULL) return -1;
152 if(gTimers[ret].Callback != NULL) continue;
153 gTimers[ret].Callback = Callback;
154 gTimers[ret].FiresAfter = giTimestamp + Delta;
155 gTimers[ret].Argument = Argument;
156 //Log("Callback = %p", Callback);
157 //Log("Timer %i fires at %lli", ret, gTimers[ret].FiresAfter);
164 * \fn void Time_RemoveTimer(int ID)
166 void Time_RemoveTimer(int ID)
168 if(ID < 0 || ID >= NUM_TIMERS) return;
169 gTimers[ID].Callback = NULL;
173 * \fn void Time_Delay(int Delay)
174 * \brief Delay for a small ammount of time
176 void Time_Delay(int Delay)
178 Sint64 dest = giTimestamp + Delay;
179 while(dest < giTimestamp) Threads_Yield();
184 EXPORT(Time_CreateTimer);
185 EXPORT(Time_RemoveTimer);