#pragma inline;

#include <bios.h>
#include <dos.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>

#define FALSE 0
#define TRUE 1

void interrupt (*old_int0B)(void);

static unsigned int fval;

unsigned long results[1000], head = 0, tail = 0;

extern void LZTimerOn();
extern void LZTimerOff();
extern unsigned long LZTimerCount();

int timer_on;

void interrupt msr_handler(void)
{
       static unsigned int tmr_count = 0, old_tmr_count = 0;
       static unsigned int half1, half2, count = 0;

       while(1) {
               if(inportb(0x2fa) & 1)                  /* Check pending int. */
                       break;
               if(! (inportb(0x2fe) & 2))              /* Check for DDSR */
                       continue;

               outportb(0x43, 0x80);                   /* Latch timer 2 */
               tmr_count = inportb(0x42);
               tmr_count |= (inportb(0x42) << 8);

               half2 = (unsigned int)(old_tmr_count - tmr_count);
               fval = half1 + half2;
               half1 = half2;
               old_tmr_count = tmr_count;

               if((fval >= 1193180/1300) && (fval <= 1193180/1100)) {
                       if(timer_on) {
                               LZTimerOff();
                               timer_on = FALSE;
                               results[head++] = LZTimerCount();
                               if(head == 1000) head = 0;
                       }
               } else {
                       if(! timer_on) {
                               LZTimerOn();
                               timer_on = TRUE;
                       }
               }
       }

       outportb(0x20, 0x20);
}



void init(void)
{
       old_int0B = getvect(0x0b);
       setvect(0x0b, msr_handler);

       asm cli;

       outportb(0x2f9, 8);                     /* Enable MS interrupt */
       outportb(0x2fc, inportb(0x2fc) | 8);    /* Activate tri-state gate */
       outportb(0x21, inportb(0x21) & 0xf7);   /* Enable IRQ3 in PIC */

       while(1) {
               inportb(0x2f8);                 /* Reset RBR */
               inportb(0x2fa);                 /* Reset IIR */
               inportb(0x2fd);                 /* Reset LSR */
               inportb(0x2fe);                 /* Reset MSR */
               if(inportb(0x2fa) & 1)          /* Loop until no pending int */
                       break;
       }

       outportb(0x61, inportb(0x61) | 1);      /* Set timer 2 gate high */
       outportb(0x43, 0xB4);                   /* Put timer 2 in mode 2 */
       outportb(0x42, 0x00);
       outportb(0x42, 0x00);

       asm sti;
}



void quit(void)
{
       asm cli;
       outportb(0x21, inportb(0x21) | 8);       /* Restore int. mask */

       setvect(0x0B, old_int0B);

       asm cli;
       outportb(0x61, inportb(0x61) & 0xfe);   /* Reset timer 2 gate */
       asm sti;
       exit(0);
}




void main(void)
{
       int c;

       init();

       LZTimerOn();
       timer_on = TRUE;

       while (1) {
               if(head != tail) {
                       printf("%06lu  ", results[tail++]);
                       if(tail == 1000) tail = 0;
               }

               if(kbhit()) {
                       getch();
                       break;
               }
       }

       quit();
}