00001 // From O'Reilly 00002 00003 enum TimerState { Idle, Active, Done }; 00004 enum TimerType { OneShot, Periodic }; 00005 00006 class Timer 00007 { 00008 public: 00009 Timer(); 00010 virtual ~Timer(); 00011 00012 int start( unsigned int nMilliseconds, TimerType =OneShot); 00013 int waitfor(); 00014 void cancel(); 00015 00016 volatile TimerState state; // Changed by some other process. 00017 TimerType type; 00018 00019 ULONG length; 00020 00021 ULONG count; // The number of ticks remaining. 00022 Timer* pNext; // For a Linked List of Timer 00023 // Ordered by the number of ticks 00024 // remaining for each timer. 00025 00026 private: 00027 // It's static because it can't manipulate software timer variable 00028 // Our interrupt service routine. 00029 static void interrupt Interrupt(); 00030 }; 00031 00032 #include "i8018xEB.h" // Declare the gProcessor global object 00033 #include "Timer.hpp" 00034 00035 #define CYCLES_PER_TICK (25000/4) 00036 /* Number of clock cycles per tick. 00037 for a 25 MHz => 25,000,000 cycles/s OR 25,000 cycles/ms 00038 and a tick takes 4 ms. 00039 00040 The software timer can have a duration from 1 to 65,535 ms, 00041 a bit more than a minute. 00042 */ 00043 00044 00045 /************************************************************************** 00046 * * 00047 * Method: Timer() * 00048 * Description: Constructor for the Timer Class. * 00049 * * 00050 * Returns: None defined. * 00051 * * 00052 **************************************************************************/ 00053 00054 Timer::Timer (void) 00055 { 00056 static int bInitialized = 0; 00057 00058 // Initialize the new software timer. 00059 00060 state = Idle; 00061 type = OneShot; 00062 length = 0; 00063 count = 0; 00064 pNext = NULL; 00065 00066 // Initialize the timer hardware, if not previously done. 00067 00068 if ( !bInitialized ) 00069 { 00070 // Install the interrupt handler and enable timer interrupts. 00071 gProcessor.installHandler( TIMER2_INT, Timer::Interrupt); 00072 gProcessor.pPCB->intControl.timerControl &= ~(TIMER_MASK | TIMER_PRIORITY ); 00073 00074 // Initialize the hardware device (using Timer #2) 00075 gProcessor.pPCB->timer[2].count = 0; 00076 gProcessor.pPCB->timer[2].maxCountA = CYCLES_PER_TICK; 00077 gProcessor.pPCB->timer[2].control = TIMER_ENABLE | TIMER_INTERRUPT | TIMER_PERIODIC; 00078 00079 // Mark the timer hardware initialized. 00080 bInitialized = 1; 00081 } 00082 00083 } /* Timer constructor */ 00084 00085 /************************************************************************** 00086 * * 00087 * Method: Start() * 00088 * Description: Start a software timer, based on the tick * 00089 * from the underlying hardware timer. * 00090 * * 00091 * Returns: 0 on success, -1 if the timer is already in use. * 00092 * * 00093 **************************************************************************/ 00094 00095 int Timer::start( unsigned int nMilliseconds, TimerType timerType ) 00096 { 00097 if ( state != Idle ) { // Timer already in use. 00098 return (-1); 00099 } 00100 00101 // Initialize the software timer. 00102 state = Active; 00103 type = timerType; 00104 length = nMilliseconds / MS_PER_TICK; 00105 00106 // Add this timer to the active timer list. 00107 timerList.insert( this ); 00108 00109 return (0); 00110 00111 } /* start() */ 00112 00113 /************************************************************************** 00114 * * 00115 * Method: Interrupt() * 00116 * Description: An interrupt handler for the timer hardware * 00117 * * 00118 * Notes: - This method is declared static, so that we cannot * 00119 * inadvertently modify any of the software timers. * 00120 * - The keyword interrupt is to ask a x86 compiler * 00121 * to save and restore every registers before and after * 00122 * that specific method (more than ordinary method call). * 00123 * * 00124 * Returns: None defined. * 00125 * * 00126 **************************************************************************/ 00127 void interrupt Timer::Interrupt() 00128 { 00129 // Decrement the active timer's count. 00130 timerList.tick(); 00131 00132 // Acknowledge the timer interrupt. 00133 gProcessor.pPCB->intControl.eoi = EOI_NONSPECIFIC; 00134 00135 // Clear the Maximum Count bit (to start the next cycle). 00136 gProcessor.pPCB->timer[2].control &= ~TIMER_MAXCOUNT; 00137 00138 } /* Interrupt() */ 00139 00140 /************************************************************************** 00141 * * 00142 * Method: waitfor() * 00143 * Description: Wait for the software timer to finish. * 00144 * * 00145 * Returns: 0 on success, -1 if the timer is not running. * 00146 * * 00147 **************************************************************************/ 00148 int Timer::waitfor() 00149 { 00150 if (state != Active) 00151 { 00152 return (-1); 00153 } 00154 00155 // Wait for the timer to expire in a stupid busy-loop. 00156 while ( state != Done); 00157 00158 // Restart or idle the timer, depending on its type. 00159 if ( type == Periodic ) 00160 { 00161 state = Active; 00162 timerList.insert( this ); 00163 } 00164 else 00165 { 00166 state = Idle; 00167 } 00168 00169 return (0); 00170 00171 } /* waitfor() */ 00172 00173 /************************************************************************** 00174 * * 00175 * Method: cancel() * 00176 * Description: Stop a running timer * 00177 * * 00178 * Returns: None defined. * 00179 * * 00180 **************************************************************************/ 00181 void Timer::cancel( void ) 00182 { 00183 // Remove the timer from the timer list. 00184 if ( state == Active ) 00185 { 00186 timerList.remove( this ); 00187 } 00188 00189 // Reset the timer's state. 00190 state = Idle; 00191 00192 } /* cancel() */ 00193 00194 Timer::~Timer() 00195 { 00196 cancel(); 00197 } 00198 00199 // Careful with Periodic timer that waitfor is never called. 00200 int Timer::poll() 00201 { 00202 return ( state == Done ); 00203 } 00204 00205 // Asynchronous CallBack 00206 00207 00208