// timer6i.c

#include <dos.h>
#include <stdio.h>
#include <bios.h>
#include "extern6i.h"

long get_timer_counter(void);
int set_up_new_timer(double freq);
void wait(double seconds);
void restore_old_timer(void);
double get_frequency(void);

void interrupt new_timer(), interrupt (far *old_timer)();

unsigned long timer_counter;
double frequency;

// save the old vector, set up new vector, zero out counter
// set up timer rate
int set_up_new_timer(double freq)
{
  unsigned ms,ls;
  double divideby;

  if(freq < (1193180.0/65536.0))
    return 0;  // can't go below this

  if(freq > 1193180.0)
    return 0;  // or above this

  divideby = 1193180.0/freq;

  divideby+=0.5; // causes a round above .5

  ms = (unsigned)divideby >> 8; // get upper 8 for ms
  ls = (unsigned)divideby & 0xff; // mask off lower 8 for ls

  frequency = 1193180.0/(double)((ms << 8) + ls);

  timer_counter = 0L;

  disable(); // turn off interrupts

  outp(0x40, ls); // least significant byte of timer count
  outp(0x40, ms);  // most significant byte of timer count

  old_timer = getvect(0x1c);

  setvect(0x1c, new_timer);

  enable(); // turn interrupts back on

  return 1;
}

// restore former table entry and rate
void restore_old_timer()
{
  disable();

  outp(0x40, 0); // least significant byte of timer count
  outp(0x40, 0);  // most significant byte of timer count

  setvect(0x1c, old_timer);

  enable();
}

// return the frequency to the caller
double get_frequency(void)
{
  return frequency;
}

// return the value of the counter to the caller
long get_timer_counter(void)
{
  return timer_counter;
}

// wait for seconds and/or fractions of a second
void wait(double seconds)
{
  long wait_count, start_count;

  if(!seconds)
    return;

  if(timer_counter < 0L)
    return;

  wait_count = (long)((seconds * frequency) + 0.5); // round at .5

  start_count = timer_counter;

  while((timer_counter - start_count) < wait_count);
}

// the interrupt handler
interrupt new_timer()
{
  disable();

  timer_counter++;

  enable();
}

// end timer6i.c

