📄 timer.cpp
字号:
/**********************************************************************
*
* Filename: timer.cpp
*
* Description: A software timer class implemented over top of the
* hardware timer within the Intel 8018xEB processor.
*
* Notes: Some of the constants in this file are specific to
* Arcom's Target188EB hardware.
*
*
* Copyright (c) 1998 by Michael Barr. This software is placed into
* the public domain and may be used for any purpose. However, this
* notice must not be changed or removed and no warranty is either
* expressed or implied by its publication or distribution.
**********************************************************************/
#include <dos.h> // For enable() and disable().
#include "i8018xEB.h"
#include "timer.h"
#ifndef NULL
#define NULL (void *) 0L
#endif
#define CYCLES_PER_TICK 6250 // Number of clock cycles per tick.
#define MS_PER_TICK 1 // Number of milliseconds per tick.
class TimerList
{
public:
TimerList();
void insert(Timer * pTimer);
Timer * remove(Timer * pTimer);
void tick(void);
private:
Timer * pTop;
};
TimerList timerList;
/**********************************************************************
*
* Function: TimerList()
*
* Description: Create and initialize a linked list of timers.
*
* Notes:
*
* Returns: None defined.
*
**********************************************************************/
TimerList::TimerList(void)
{
pTop = NULL;
} /* TimerList() */
/**********************************************************************
*
* Method: insert()
*
* Description: Insert a timer into an ordered linked list.
*
* Notes: This routine disables interrupts.
*
* Returns: None defined.
*
**********************************************************************/
void
TimerList::insert(Timer * pTimer)
{
Timer ** ppPrev = &this->pTop;
disable();
//
// Initialize the new timer's tick count.
//
pTimer->count = pTimer->length;
//
// Walk down the timer list, subtracting ticks as we go.
//
while (*ppPrev != NULL && pTimer->count >= (*ppPrev)->count)
{
pTimer->count -= (*ppPrev)->count;
ppPrev = &(*ppPrev)->pNext;
}
//
// Insert the new timer at this point in the timer list.
//
pTimer->pNext = *ppPrev;
*ppPrev = pTimer;
//
// Adjust the tick count of the next timer (if any).
//
if (pTimer->pNext != NULL)
{
pTimer->pNext->count -= pTimer->count;
}
enable();
} /* insert() */
/**********************************************************************
*
* Method: remove()
*
* Description: Remove a timer from the timer list.
*
* Notes: This routine disables interrupts.
*
* Returns: A pointer to the removed timer, NULL if it wasn't
* found in the timer list.
*
**********************************************************************/
Timer *
TimerList::remove(Timer * pTimer)
{
Timer ** ppPrev = &this->pTop;
disable();
//
// Walk down the linked list until the dead timer is found.
//
while (*ppPrev != NULL && *ppPrev != pTimer)
{
ppPrev = &(*ppPrev)->pNext;
}
//
// Remove the dead timer from the linked list.
//
if (*ppPrev != NULL)
{
*ppPrev = pTimer->pNext;
(*ppPrev)->count += pTimer->count;
}
enable();
return (*ppPrev);
} /* remove() */
/**********************************************************************
*
* Method: tick()
*
* Description: Update the linked list of timers for a clock tick.
*
* Notes: The caller is responsible for disabling interrupts.
*
* Returns: None defined.
*
**********************************************************************/
void
TimerList::tick()
{
Timer ** ppTop = &this->pTop;
if (*ppTop != NULL)
{
//
// Decrement the tick count of the first timer in the list.
//
(*ppTop)->count--;
//
// Mark all of the expired timers done and remove them.
//
while (*ppTop != NULL && (*ppTop)->count == 0)
{
(*ppTop)->state = Done;
*ppTop = (*ppTop)->pNext;
}
}
} /* tick() */
/**********************************************************************
*
* Method: Interrupt()
*
* Description: An interrupt handler for the timer hardware.
*
* Notes: This method is declared static, so that we cannot
* inadvertently modify any of the software timers.
*
* Returns: None defined.
*
**********************************************************************/
void interrupt
Timer::Interrupt()
{
//
// Decrement the active timer's count.
//
timerList.tick();
//
// Acknowledge the timer interrupt.
//
gProcessor.pPCB->intControl.eoi = EOI_NONSPECIFIC;
//
// Clear the Maximum Count bit (to start the next cycle).
//
gProcessor.pPCB->timer[2].control &= ~TIMER_MAXCOUNT;
} /* Interrupt() */
/**********************************************************************
*
* Method: Timer()
*
* Description: Constructor for the Timer class.
*
* Notes:
*
* Returns: None defined.
*
**********************************************************************/
Timer::Timer(void)
{
static int bInitialized = 0;
//
// Initialize the new software timer.
//
state = Idle;
type = OneShot;
length = 0;
count = 0;
pNext = NULL;
//
// Initialize the timer hardware, if not previously done.
//
if (!bInitialized)
{
//
// Install the interrupt handler and enable timer interrupts.
//
gProcessor.installHandler(TIMER2_INT, Timer::Interrupt);
gProcessor.pPCB->intControl.timerControl &=
~(TIMER_MASK | TIMER_PRIORITY);
//
// Initialize the hardware device (use Timer #2).
//
gProcessor.pPCB->timer[2].count = 0;
gProcessor.pPCB->timer[2].maxCountA = CYCLES_PER_TICK;
gProcessor.pPCB->timer[2].control = TIMER_ENABLE
| TIMER_INTERRUPT
| TIMER_PERIODIC;
//
// Mark the timer hardware initialized.
//
bInitialized = 1;
}
} /* Timer() */
/**********************************************************************
*
* Method: ~Timer()
*
* Description: Destructor for the Timer class.
*
* Notes: This routine ensures that the timer isn't left dangling
* in the timer list.
*
* Returns: None defined.
*
**********************************************************************/
Timer::~Timer(void)
{
//
// Cancel the timer.
//
this->cancel();
} /* ~Timer() */
/**********************************************************************
*
* Method: start()
*
* Description: Start a software timer, based on the tick from the
* underlying hardware timer.
*
* Notes:
*
* Returns: 0 on success, -1 if the timer is already in use.
*
**********************************************************************/
int
Timer::start(unsigned int nMilliseconds, TimerType timerType)
{
if (state != Idle)
{
return (-1);
}
//
// Initialize the software timer.
//
type = timerType;
length = nMilliseconds / MS_PER_TICK;
state = Active;
//
// Add this timer to the active timer list.
//
timerList.insert(this);
return (0);
} /* start() */
/**********************************************************************
*
* Method: waitfor()
*
* Description: Wait for the software timer to finish.
*
* Notes:
*
* Returns: 0 on success, -1 if the timer is not running.
*
**********************************************************************/
int
Timer::waitfor()
{
if (state != Active)
{
return (-1);
}
//
// Wait for the timer to expire.
//
while (state != Done);
//
// Restart or idle the timer, depending on its type.
//
if (type == Periodic)
{
state = Active;
timerList.insert(this);
}
else
{
state = Idle;
}
return (0);
} /* waitfor() */
/**********************************************************************
*
* Method: cancel()
*
* Description: Stop a running timer.
*
* Notes:
*
* Returns: None defined.
*
**********************************************************************/
void
Timer::cancel(void)
{
//
// Remove the timer from the timer list.
//
if (state == Active)
{
timerList.remove(this);
}
//
// Reset the timer's state.
//
state = Idle;
} /* cancel() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -