Listing 2: Timer implementation

#include<bios.h>  //  the time function.
#include"timer.h"

int TIMER::executive_tic(void)
{
  long current_time = biostime(_TIME_GETCLOCK, current_time);
  if (last_bios_time != current_time) { //18.2 Hz, 54 ms
    last_bios_time = current_time;
    ++time_count %= count_mod;
    return 1;
  }
  return 0;
}

TIMER_HANDLE TIMER::open_timer(float seconds)
{
  //  Find a free handle.
  for (int i=search_next_handle_start;
       timer_used[i] && i<max_timers; i++);
  search_next_handle_start = 0;
  if(i==max_timers) return -1; //error, all timers are used.
  timer_used[i] = true;
  timer_expired[i] = false;
  if (seconds < 0.05) timer_expired[i] = true;
  expire_time[i] = (time_count + int(18.2 * seconds)) % count_mod;
  return i;
}

boolean TIMER::expired(const TIMER_HANDLE &handle)
{
  if (handle < 0 || handle >= max_timers) return true;
  if (timer_expired[handle]) return true;
  //  There is a 2 second window (36 tics) for expired to be
  //  called and have it know it is expired.  Otherwise it thinks
  //  that the time interval wraps-around our circular counter.
  //  Everybody should be executing faster than a 1 hz rate, so a
  //  2 second window should be sufficient.
  if ((time_count - expire_time[handle] + count_mod) %
       count_mod > 36)
    return false;  
  //  If execution reaches here, then time has expired.
  timer_expired[handle] = true;
  return true;
}

//  Return time left in seconds.
float TIMER::time_left(const TIMER_HANDLE &handle)
{
  if (handle < 0 || handle >= max_timers) return 0.0;
  if (timer_expired[handle]) return 0.0;
  int diff_time = expire_time[handle] - time_count;
  if (diff_time < -36) return float(diff_time + count_mod)/18.2;
  if (diff_time > 0) return float(diff_time)/18.2;
  return 0.0;
}

void TIMER::close_timer(TIMER_HANDLE &handle)
{
  if (handle >= 0 && handle < max_timers) {
    timer_used[handle] = false;
    search_next_handle_start = handle;
  }
  handle = -1;
}

TIMER::TIMER(void): count_mod(4096)
    //  count_mod is an arbitrary number right now.  turn over
    //  about 4 min.
{
  for (int i=0; i<max_timers; i++) {
    timer_used[i] = false;
    timer_expired[i] = false;
    expire_time[i] = 0;
  }
  last_bios_time = biostime(_TIME_GETCLOCK,
last_bios_time);
  time_count = 0;
  search_next_handle_start = 0;
}
//End of File