/*
*
*      Acceptence Test Procedure Guidance Program   ---  C Source Code
*
*/

/*
*     source file:   ATP1.C
*     written by:    DMY
*
*/

/*
* --->>>  Revision History
*
* $ Revision:   1.0 $
*     $ Date:     April 29, 1991   11:16:17 $
*      $ Log:   c:\st8a\ver\atp1.c_v $
*
*     Rev 1.0     April 29, 1991   11:16:17 $
*  - Initial Revision
*
*/

/*
*     description: This automated Acceptence Test Procedure program must be
*                  used in conjuction with a ST-8000A.  This program is meant
*                  to automate the procedures of the ATP in HAL's document
*                  #0794-1E001-001.  This program will display those pro-
*                  cedures on a screen and handle most of the control of the
*                  ST-8000A via COM1.
*
*/

/*
*     include files:
*
*           *.h      - standard C headers from Turbo C Plus Plus
*     articl1.def    - Text and data structures for this program
*
*/


#include <stdlib.h>
#include <process.h>
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <bios.h>
#include <float.h>
#include <ctype.h>
#include <time.h>
#include "atp1.def"

#define  com_set    0           /* for final bioscom to reset async port */
#define  baud_30    3840
#define  baud_50    2304
#define  baud_110   1047
#define  baud_300   384
#define  baud_600   192         /* async port baud divisors */
#define  baud_1200  96
#define  baud_2400  48
#define  baud_4800  24
#define  baud_9600  12
#define  baud_19200 06
#define  dbits_8    0x03        /* # of data bits for async setup */
#define  dbits_5    0x00        /* # of data bits for async setup */
#define  sbits_1    0x00        /* stop bits for async setup */
#define  sbits_2    0x04
#define  no_parity  0x00        /* parity declaration for async setup */
#define  setup1     dbits_8 | sbits_2 | no_parity
#define  setup2     dbits_5 | sbits_2 | no_parity

#define  data_ready 0x01        /* data ready mask for async status */
#define  thre       0x20        /* lsr, transmit holding register empty bit */
#define  tsre       0x40        /* lsr, transmit shift register empty bit */
#define  com1       0x3f8       /* address for com1's 8250 */
#define  com2       0x2f8       /* address for com2's 8251 */
#define  ien        0x01        /* index to interrupt enable reg of 8250 */
#define  lcr        0x03        /* index to line control register of 8250 */
#define  mcr        0x04        /* index to modem control register of 8250 */
#define  lsr        0x05        /* index to line status register of 8250 */
#define  msr        0x06        /* index to modem status register of 8250 */

#define  ictrlr     0x20        /* address for interrupt controller of pc */
#define  intmask1   0xEF        /* int mask to enable com1 in 8259 */
#define  intmask2   0xF7        /* int mask to enable com2 in 8259 */
#define  intrset    0x20        /* 8259 reset interrupt code */

#define  bufsiz1    2048        /* buffer size for com1 receive interrupt */
#define  bufsiz2    2048        /* buffer size for com2 receive interrupt */

char  buf1[bufsiz1];            /* receive int buffer for remote port */
int   begin1;                   /* output index for receive buffer */
int   end1;                     /* input index for receive buffer */
void interrupt (*oldasync1)();  /* pointer to old async int handler */

char  buf2[bufsiz2];            /* receive int buffer for data port */
int   begin2;                   /* output index for receive buffer */
int   end2;                     /* input index for receive buffer */

char  name[30];                 /* testing tech's name */
char  serial[10];               /* serial number */

void interrupt (*oldasync2)();  /* pointer to old async int handler */

char  cmntbuf[80*25];           /* holds up to one page of comments */
char *cmntptr;

int  tcnt;                      /* log count */

/* function call prototypes */
int  getcr(int);
int  yorn_data(int);
int  key_test(int);
int  exitkey(int, int);
int  kb_key(int);
int  txrx_qbf(int);
int  test_info(int);
int  float_data(int);
int  log_error(int);
int  read_status(int);
int  read_BIT(int);
int  com_string(char *, int);
int  test_kb(int);
int  test_cd(int);
int  msure_delay(int);
int  scan(int, char *, int);
void beep(void);
void errbeep(void);
int  setup_com(int, int, char);
int  put_com(int, char, int);
int  puts_com(int, char *, int);
char get_com(int);
void interrupt comint1(void);
void interrupt comint2(void);
void to_exit(int);
char *comment(void);

/*
*   The main function.  Loops here through all the pages of the First
*   Article Procedures.  Calls any needed programs and allows direction
*   control.
*/

int main(void)
{
    int   result, i, count, j;
    char  *ptr, ch;

    directvideo = 1;
                                /* put function addresses in the array */
    pfa[0] = getcr;             /* waits for a cr from keyboard */
    pfa[1] = yorn_data;         /* Get Yes or No test results */
    pfa[2] = key_test;          /* keypad test function */
    pfa[3] = float_data;        /* get floating point data from user */
    pfa[4] = float_data;        /* get floating point data from user */
    pfa[5] = float_data;        /* get floating point data from user */
    pfa[6] = float_data;        /* get floating point data from user */
    pfa[7] = read_status;       /* wait for g3 status page from ST-8000A */
    pfa[8] = txrx_qbf;          /* Tx & Rx QBF via ST-8000A data port */
    pfa[9] = test_cd;           /* send some data to exercise CD on unit */
    pfa[10] = msure_delay;      /* send data to measure CD or MUTE delay */
    pfa[11] = read_BIT;         /* Verify bit runs and passes via scan */
    pfa[12] = test_info;        /* get tech name and unit serial number */
    disable();
    oldasync1 = getvect(0x0c);  /* save old primary async handler address */
    setvect(0x0c,comint1);      /* install new async handler */
    oldasync2 = getvect(0x0b);  /* save old secondary async handler address */
    setvect(0x0b,comint2);      /* install new async handler */
    enable();
    tcnt = 0;
    cmntptr = &cmntbuf[0];

                 /* for each instruction page structure */
    for(count = 0; count < nbr_instr; ++count)
    {
        if(instr[count].cls != 00)  clrscr();

                 /* display the instruction page */

        printf("%s",instr[count].tmsg);

                /* call some functions associated with the instruction */

        result = 0;
        if(instr[count].action) /* send configure string to ST-8000A? */
        {
            result = com_string(instr[count].cstr, count);
        }
        if(result)
        {                       /* neg if to backup to last section */
            count = instr[count].bline;
            --count;
        }                       /* subtract against for's incr */
        else                    /* call 1 of 6 data input routine */
        {
            result = (*pfa[instr[count].typdata])(count);
            if(result == -1)
            {                                   /* previous section */
                count = instr[count].bline;
                switch(count)
                {
                    case 0:
                    case 3:
                            tcnt = 0;           /* only four sections */
                            break;
                    case 6:                     /* to back up towards */
                            tcnt = 3;
                            break;
                    case 10:
                            tcnt = 8;
                            break;
                    case 25:
                            tcnt = 22;
                            break;
                    default:
                            printf("\r\nUnknown Section Start\n");
                }
                --count;
            }
            else if(result == -2)               /* or repeat */
            {
                --count;
            }
        }
    }
    to_exit(count);                  /* done */
}



int  com_string(char *conf, int number)  /* send inconspicuous string to 8000A */
{
    char  *ptr, ch, chr, st;
    int   status, i, j;
    time_t  start, current;


    ptr = conf;
    setup_com(com1,baud_9600,setup1);          /* faster faster */
    while(*ptr)
    {
        if(put_com(com1,*ptr,number))          /* send supplied string to com1 */
        {
            to_exit(number);                  /* quit if no one is home */
        }
        ++ptr;

        if(test_kb(number)) return(-1);
    }
    start = time(NULL);
    while(1)                            /* Full duplex */
    {
        ch = get_com(com1);
        if(ch == '\r')                  /* display echoed chars until a cr */
        {
            while(get_com(com1) != '\n')  /* wait for dangling newline */
            {
                if(test_kb(number)) return(-1); /* allow exit/back up, if stuck */
            }
            return(0);
        }
        current = time(NULL);
        if(difftime(current,start) >= 10)
        {
            printf("\r\n ERROR...No ECHO from Remote Port!!\r\nPress <Enter>...");
            getch();
            to_exit(number);
        }

        if(test_kb(number)) return(-1);       /* allow exit/back up, if stuck */
    }

}


int test_info(int number)  /* get techs name and units serial number */
{
    char ch;
    int  i;
    struct time  t;
    struct date  d;
    unsigned int  c1, c2, c3;

    if(getcr(number)) return(-1);
    clrscr();
    printf("%s",notes);
    printf("\r\n\n       TEST INFORMATION INPUT ");
    printf("\r\n\nEnter your name or initials: ");
    for (i = 0; i < 25; ++i)
    {
        ch = getch();
        if(ch == 0x1b)  to_exit(number);  /* <ESC> to exit the program */
        else if(!ch)            /* check for special char, 00h, */
        {
            ch = getch();
            if(ch == 'I')       /* 00h, 47h is <Pg Up> */
                  return(-1);   /* so backup once */
        }
        else if(ch == '\r')     /* end on cr */
        {
            break;
        }
        else if(ch == '\b')     /* allow rudimentary editing */
        {
            --i;
            if(i >= 0)
            {
                putch('\b');
                putch(' ');
                putch('\b');
                --i;
            }
        }
        else                    /* a valid character */
        {
            putch(ch);
            name[i] = ch;      /* squirrel it away */
        }
    }
    name[i] = '\0';             /* terminate name string */
    if(i >= 25) printf("..ENOUGH!!");
    fflush(stdin);

    printf("\r\n\nEnter ST-8000A's Serial Number: ");

    for (i = 0; i < 7; ++i)
    {
        ch = getch();
        if(ch == 0x1b)  to_exit(number);  /* <ESC> to exit the program */
        else if(!ch)            /* check for special char, 00h, */
        {
            ch = getch();
            if(ch == 'I')       /* 00h, 47h is <Pg Up> */
                  return(-1);   /* so backup once */
        }
        else if(ch == '\r')     /* end on cr */
        {
            break;
        }
        else if(ch == '\b')     /* allow rudimentary editing */
        {
            --i;
            if(i >= 0)
            {
                --i;
                putch('\b');
                putch(' ');
                putch('\b');
            }
        }
        else                    /* a valid character */
        {
            putch(ch);
            serial[i] = ch;     /* squirrel it away */
        }
    }
    serial[i] = '\0';             /* terminate name string */
    if(i >= 7) printf("..ENOUGH!!");
    fflush(stdin);

    putch('\n');
    do
    {
        getdate(&d);
        gettime(&t);
        printf("\r\nCurrent Time is  %2d:%02d:%02d",t.ti_hour,t.ti_min,t.ti_sec);
        printf("\r\nCurrent Date is  %d-%d-%d",d.da_mon,d.da_day,d.da_year);
        printf("\r\n\nPress <Enter> or 'C' to change time or date: ");

        i = 0;
        while(1)
        {
            ch = toupper(getch());      /* allow date and time change */
            if(ch == '\r')  break;
            else if(ch == 'C')
            {
                putch(ch);
                printf("\r\n\n Enter new time as xx:xx - ");
                scanf("%u:%u",&c1,&c2);  /* get hours and mins of new time */
                fflush(stdin);           /* clear input stream */
                t.ti_hour = c1;
                t.ti_min = c2;          /* set the time */
                t.ti_sec = 00;
                settime(&t);
                printf("\r Enter new date as xx-xx-19xx : ");
                scanf("%u-%u-%u",&c1,&c2,&c3);  /* get the new date */
                fflush(stdin);
                d.da_mon = c1;          /* set the new date in it's struct */
                d.da_day = c2;
                d.da_year = c3;
                setdate(&d);            /* set the new date */
                i = 1;
                break;
            }
        }
    }while(i);

    return(0);
}




int getcr(int number)     /* wait for a cr */
{
    char ch;

    while ((ch = getch()) != '\r')
    {
        if(ch == 0x1b)  to_exit(number);  /* <ESC> to exit the program */
        else if(!ch)            /* check for special char, 00h, */
        {
            ch = getch();
            if(ch == 'I')       /* 00h, 47h is <Pg Up> */
                  return(-1);   /* so backup once */
        }
    }
    return(0);
}


int yorn_data(int number)  /* Get Y or N test results, if N, allow comments */
{
    char ch;
    int  result;

    printf("%s",instr[number].dmsg);
    while (1)                /* continue until we get the char we want */
    {
        ch = getch();
        ch = tolower(ch);
        if(ch == 0x1b)          /* exit program on escapes */
        {
            to_exit(number);
        }
        else if(ch == 'y')              /* everything is OK */
        {
            printf("Yes");              /* echo back the result */
            tlog[tcnt].result = 1;      /* store the result as good */
            tlog[tcnt].typdata = instr[number].typdata;
            tlog[tcnt++].comnt = NULL;  /* no comment pointer */
            break;                      /* go on to next step */
        }
        else if(ch == 'n')              /* looks like a failure */
        {
            printf("No");               /* echo the char */
            return(log_error(number));
        }
        else if(ch == 'r')
        {                               /* send back repeat flag */
            printf("Repeat");
            return(-2);
        }
    }
    printf("\r\n");
    return(0);
}


int float_data(int number)   /* Get and check floating point result data */
{
    char  array1[10] = "-2345.789";
    char  ch, *ptr;
    int   error, count, alpha, deci;
    float indata;

    printf("%s",instr[number].dmsg);

    ptr = array1;                   /* pointer for floating point number string */
    alpha=count=deci=0;             /* clear flags */
    while(count <= 8)
    {
        ch = getch();
        if(ch == 0x1b)              /* reset request */
        {
            if(!count)  to_exit(number);  /* <ESC> to exit the program */
            return(float_data(number)); /* or start input over */
        }
        if(!ch)                     /* check for special char, 00h, */
        {
            ch = getch();
            if(ch == 'I')           /* 00h, 47h is <Pg Up> */
                return(-1);         /* so backup once */
        }
        else if(ch == '\r')         /* end input request */
        {
            if(alpha)  break;
            tlog[tcnt].data1 = -9999.99; /* load log with obscure data */
            tlog[tcnt].typdata = instr[number].typdata;
            return(log_error(number));     /* if no data was entered */
        }
        else if(isdigit(ch))        /* if 0 to 9 */
        {
            putch(ch);              /* echo char */
            ++alpha;                /* 1 valid number received */
            ++count;
            *ptr++ = ch;            /* save in string */
        }
        else if((ch == '-') && !count) /* negative on first digit only */
        {
            putch(ch);              /* echo the character entered */
            *ptr++ = ch;
            ++count;
        }
        else if((ch == '.') && !deci)  /* one decimal only */
        {
            putch(ch);              /* echo the character entered */
            *ptr++ = ch;
            ++deci;                 /* flag 'decimal was received' */
            ++count;
        }
        else if((ch == '\b') && count)  /* edit with backspace */
        {
            --count;                /* reduce the count */
            --ptr;                  /* and backup the pointer */
            if(*ptr == '.')  deci = 0;
            if(isdigit(*ptr)) --alpha;
            putch(ch);
            putch(' ');             /* clear previous char on the screen */
            putch(ch);
        }
    }
    if(!alpha)                      /* if no valid data then force error */
    {
        tlog[tcnt].data1 = -9999.99; /* load log with obscure data */
        tlog[tcnt].typdata = instr[number].typdata;
        return(log_error(number));     /* if no data was entered */
    }
    *ptr = '\0';
    indata = (float)atof(array1);

    tlog[tcnt].data1 = indata;
    error = 0;
    if(indata < instr[number].datalo)
    {
        printf("\r\n ERROR...Data is below allowable range!!\r\n");
        return(log_error(number));
    }
    else if(indata > instr[number].datahi)
    {
        printf("\r\n ERROR...Data is above allowable range!!\r\n");
        return(log_error(number));
    }
    tlog[tcnt].typdata = instr[number].typdata;
    tlog[tcnt++].result = 1;
    return(0);
}


int log_error(int number)
{
    char  ch;

    tlog[tcnt].result = 0;    /* log the result */
    tlog[tcnt].typdata = instr[number].typdata;
    tlog[tcnt++].comnt = comment();  /* log the comment */
    printf("\r\n\nPress <Enter> to continue error exit or <sp> to repeat...");
    ch = getch();
    if(ch == ' ')
    {
        --tcnt;                 /* on repeats decrement the result counter */
        return(-2);
    }
    to_exit(number);
}



int read_status(int number)  /* read G3 status page from ST-8000A */
{
    int  stats;
    char *ptr;
    char ch;


    if(getcr(number)) return(-1);       /* wait for cr */
    printf("WAIT!...");
    ptr = "G3\r";
    while(*ptr)                         /* initiate status page */
    {
        put_com(com1,*ptr,number);             /* start BIT Menu via com1 */
        ++ptr;
        if(test_kb(number)) return(-1); /* allow exit/back up, if stuck */
    }

    stats = scan(com1,"(CH 2)  =  ", number);
    if(stats < 0)  return(-1);
    if(stats > 0)
    {
        printf("\r\n ERROR...G3 status not returned!!\r\n");
        return(log_error(number));
    }
    stats = scan(com1,"\n", number);
    if(stats < 0)  return(-1);
    if(stats > 0)
    {
        printf("\r\n ERROR...G3 status not returned!!\r\n");
        return(log_error(number));
    }
    printf("Received G3 status page!!\r\n");
    delay(1500);              /* just wait a second */
    while(get_com(com1) != -1)
    {                         /* flush the port */
        if(test_kb(number)) return(-1); /* allow exit/back up, if stuck */
    }
    tlog[tcnt].typdata = instr[number].typdata;
    tlog[tcnt++].result = 1;
    return(0);
}


int read_BIT(int number)  /* verify BIT runs and passes via scan */
{
    int  i, stats;
    char *ptr = "1";
    char ch, *ptr1;


    if(getcr(number)) return(-1);     /* wait for an Enter */
    setup_com(com1,baud_9600,setup1); /* faster faster */
    ptr1 = "c1c1c1r1t1\r";
    while(*ptr1)
    {
        put_com(com1,*ptr1,number);         /* start BIT Menu via com1 */
        ++ptr1;
        if(test_kb(number)) return(-1);    /* allow exit/back up, if stuck */
    }
    printf(" Observe Front Panel...");
    delay(30);                          /* give unit some time */
    stats = scan(com1,"BUILT-IN-TEST", number);
    if(stats < 0)  return(-1);          /* get headr message */
    if(stats > 0)
    {
        printf("\r\n ERROR...BIT text not received!!\r\n");
        return(log_error(number));
    }
    for(ch = '1'; ch <= '9'; ++ch)      /* get # and pass for tests 1 to 9 */
    {
        *ptr = ch;
        stats = scan(com1,ptr,number);
        if(stats < 0)  return(-1);
        if(stats > 0)
        {
            printf("\r\n ERROR...BIT text not received!!\r\n");
            return(log_error(number));
        }
        stats = scan(com1,"PASSED",number);
        if(stats < 0)  return(-1);
        if(stats > 0)
        {
            printf("\r\n ERROR...BIT text not received!!\r\n");
            return(log_error(number));
        }
    }
    stats = scan(com1,"THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG'S BACK 0123456789",number);
    if(stats < 0)  return(-1);
    if(stats > 0)                       /* verify the first qbf */
    {
        printf("\r\n ERROR...BIT text not received!!\r\n");
        return(log_error(number));
    }
    tlog[tcnt].typdata = instr[number].typdata;
    tlog[tcnt++].result = 1;
    stats = scan(com1,"ST-8000A PASSED ALL TESTS.",number);
    if(stats < 0)  return(-1);
    if(stats > 0)                       /* get pass message from bit */
    {
        printf("\r\n ERROR...BIT PASS message not received!!\r\n");
        return(log_error(number));
    }
    tlog[tcnt].typdata = instr[number].typdata;
    tlog[tcnt++].result = 1;
    printf("BIT indicates PASS!! ");
    delay(1000);
    printf("\r\nWaiting for ST-8000A to Reset...\r\n");
    delay(7500);               /* just wait a few seconds */
    return(yorn_data(number));
}


int  key_test(int number)       /* Run Keypad Input Tests */
{
    char  *ptr, ch, ch1, chr;
    int   i, keyvalue, error, stats;

    setup_com(com1,baud_9600,setup1); /* faster faster */
    ptr = "c01r1t9\r\n";
    while(*ptr)
    {
        put_com(com1,*ptr,number);          /* start BIT Menu via com1 */
        ++ptr;
        if(kb_key(number)) return(-1);     /* allow exit/back up, if stuck */
    }

    stats = scan(com1,">> ",number);        /* wait for menu and prompt */
    if(stats < 0) return(exitkey(-1,number));
    if(stats > 0)
    {
        printf("\r\n ERROR...Menu and prompt not received!!\r\n");
        return(exitkey(log_error(number),number));
    }
    put_com(com1, 'K',number);              /* select the keypad test in BIT */
    stats = scan(com1,"----\r\n",number);   /* wait for begin of key test */
    if(stats < 0)  return(exitkey(-1,number));
    if(stats > 0)
    {
        printf("\r\n ERROR...Key Test prompt not received!!\r\n");
        return(exitkey(log_error(number),number));
    }

    printf("\r\nST-8000A KEYPAD TEST");
    printf("\r\n\n Press the Key indicated");
    printf("\r\n   -One short beep = key is ok!");
    printf("\r\n   -Four short beeps = key failed!\r\n");
    error = 0;
    for(i = 0; i < 27; ++ i)
    {
        printf("\r\n Press the %s key -- ", keystr[i]);
        while(1)
        {
            while(get_com(com1) != ' ')          /* wait for the first space */
            {
                if(kb_key(number)) return(-1);         /* allow exit/back up, if stuck */
            }
            while((ch = get_com(com1)) != ' ')   /* wait for the key string */
            {
                if(ch != -1) putch(ch);          /* and display it */
                if(kb_key(number)) return(-1);         /* allow exit/back up, if stuck */
            }
            do                                   /* wait during spaces before */
            {                                    /* the scan code */
                if(kb_key(number)) return(-1);         /* allow exit/back up, if stuck */
                ch = get_com(com1);
            }while((ch == -1) || (ch == ' '));
                                                 /* 1st char is msb of scan code */
            if(ch < 'A') ch &= 0x0f;             /* turn it into hex int */
            else ch = (ch & 0x0f) + 9;
            keyvalue = ch << 4;
            while((ch = get_com(com1)) == -1)    /* wait for next scan char */
            {
                if(kb_key(number)) return(-1);         /* allow exit/back up, if stuck */
            }
            if(ch < 'A') ch &= 0x0f;             /* make lsb scan char hex */
            else ch = (ch & 0x0f) + 9;
            keyvalue |= ch;                      /* combine digits of scan */
            if(keyvalue != keycode[i])           /* test key */
            {                                    /* wrong key */
                errbeep();                       /* do error beeps */
                if(++error > 1)                  /* unit fails if two errors */
                {                                /* from the same key */
                    printf("\r\n\n  Unit Failed KeyPad Test!!!");
                    return(exitkey(log_error(number),number));
                }
                --i;
                break;
            }
            else                        /* correct key */
            {
                beep();                 /* give reassurance beep */
                error = 0;              /* reset error count */
                break;
            }
        }
    }

    put_com(com1,'\r',number);                 /* terminate key test */
    stats = scan(com1,">> ",number);           /* wait for menus prompt */
    if(stats < 0)  return(exitkey(-1,number));
    if(stats > 0)
    {
        printf("\r\n ERROR...Menu Prompt not received!!\r\n");
        return(exitkey(log_error(number),number));
    }

    put_com(com1,'X',number);                  /* exit BIT Menu */
    put_com(com1,'\r',number);
    printf("%s",instr[number].dmsg);    /* print exit and wait message */
    delay(5000);                        /* wait for the system to reset */
    printf(" OK!\r\n");
    tlog[tcnt].typdata = instr[number].typdata;
    tlog[tcnt++].result = 1;
    return(0);
}


int  kb_key(int number)                   /* keyboard check just for key test */
{
    char chr;

    if(kbhit())                     /* quit on an ESC */
    {
        chr = getch();
        if(chr == 0x1b)
        {                           /* disable BIT Menu */
            put_com(com1,'\r',number);
            delay(1000);            /* exit key test then menu test */
            put_com(com1,'X',number);
            delay(5000);
            to_exit(number);              /* <ESC> to exit the program */
        }
        if(!chr)                    /* check for special char, 00h, */
        {
            chr = getch();
            if(chr == 'I')          /* 00h, 47h is <Pg Up> */
            {
                put_com(com1,'\r',number);
                delay(1000);        /* exit key test then menu test */
                put_com(com1,'X',number);
                delay(5000);
                return(-1);         /* so backup once */
            }
        }
    }
    return(0);
}


int  exitkey(int ret_val, int number)
{
    put_com(com1,'\r',number);
    delay(1000);                 /* exit key test then menu test */
    put_com(com1,'X',number);
    delay(5000);
    return(ret_val);
}



char qbuf[100] = { 0x10,0x14,0x01,0x04,0x17,0x07,0x06,0x0e,0x0f,0x04,0x19,0x0a,0x18,
                 0x13,0x0c,0x04,0x0d,0x18,0x1d,0x04,0x0b,0x07,0x1c,0x16,0x01,0x09,
                 0x04,0x18,0x1e,0x01,0x0a,0x04,0x10,0x14,0x01,0x04,0x12,0x03,0x11,
                 0x15,0x04,0x09,0x18,0x1a,0x04,0x1b,0x17,0x13,0x01,0x0a,0x10,0x15,
                 0x07,0x06,0x18,0x16,0x00};

int  txrx_qbf(int number)       /* Tx & Rx QBF across ST-8000A data port */
{
    char  *ptr, chr;
    int   i, stats;

    ptr = "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG\'S BACK 0123456789\r\n";
    if(instr[number].datalo < 0.0)              /* 8bit, 30baud if negative */
    {
        setup_com(com2,baud_30,setup1);
    }
    else if(instr[number].datahi < 0.0)         /* 600baud, 5bit if negative */
    {
        setup_com(com2,baud_600,setup2);
        ptr = &qbuf[0];                         /* strip down to 5 bit data */
    }
    else                                        /* both pos, 600baud, 8bit */
    {
        setup_com(com2,baud_600,setup1);
    }
    while(!kbhit())
        ;
    chr = getch();
    if(chr == 0x1b)  to_exit(number); /* <ESC> to exit the program */
    if(!chr)                    /* check for special char, 00h, */
    {
        chr = getch();
        if(chr == 'I')          /* 00h, 47h is <Pg Up> */
            return(-1);         /* so backup once */
    }

    printf("\r\nSending QBF across the data port...WAIT!");
    stats = puts_com(com2,ptr,number);
    if(stats < 0) return(stats);
    else if(stats > 0)
    {
        printf("\r\n ERROR...Timed Out while sending text!!");
        return(log_error(number));
    }

    stats = scan(com2,ptr,number);          /* wait for QBF to return */
    if(stats < 0)  return(-1);
    if(stats > 0)
    {
        printf("\r\n ERROR...QBF not received!!\r\n");
        return(log_error(number));
    }
    printf(" ....QBF received error free!!\r\n");
    delay(1500);
    tlog[tcnt].typdata = instr[number].typdata;
    tlog[tcnt++].result = 1;
    return(0);
}



int  test_cd(int number)           /* send some data to exercise CD on unit */
{
    char  chr;
    int   stats;

    setup_com(com2,baud_600,setup1);    /* Radio Speed */

    while(!kbhit())
        ;
    chr = getch();
    if(chr == 0x1b)  to_exit(number); /* <ESC> to exit the program */
    if(!chr)                    /* check for special char, 00h, */
    {
        chr = getch();
        if(chr == 'I')          /* 00h, 47h is <Pg Up> */
            return(-1);         /* so backup once */
    }

    printf("...Sending");
    stats = puts_com(com2,"\r\r",number);
    if(stats < 0) return(stats);
    else if(stats > 0)
    {
        printf("\r\n ERROR...Timed Out while sending text!!");
        return(log_error(number));
    }
    printf("...Done!");
    return(yorn_data(number));   /* get results on way out */
}




int  msure_delay(int number)       /* send data to measure CD or MUTE delay */
{
    char  *ptr, ch, ch1, chr;
    int   i, error, stats;

    setup_com(com2,baud_600,setup1);    /* Radio Speed */

    while(!kbhit())
        ;
    chr = getch();
    if(chr == 0x1b)  to_exit(number); /* <ESC> to exit the program */
    if(!chr)                    /* check for special char, 00h, */
    {
        chr = getch();
        if(chr == 'I')          /* 00h, 47h is <Pg Up> */
            return(-1);         /* so backup once */
    }

    ptr = "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG\'S BACK 0123456789\r\n";
    printf("\r\nSending QBF...");
    stats = puts_com(com2,ptr,number);
    if(stats < 0) return(stats);
    else if(stats > 0)
    {
        printf("\r\n ERROR...Timed Out while sending text!!");
        return(log_error(number));
    }

    printf("...Done!");
    return(float_data(number));   /* get results on way out */
}





int  scan(int port, char *scanstr, int number)       /* read the com port for string */
{
    char *ptr, ch, chr;
    time_t  start, current;

    ptr = scanstr;                      /* get address of string to find */
    start = time(NULL);
    while(1)                            /* Wait until prompt is displayed */
    {
        ch = get_com(port);
        if(ch == *ptr)                  /* if a match */
        {
            if(!*++ptr) return(0);      /* inc ptr, return at end of string */
        }
        else                            /* no match */
        {
            if(ch != -1)                /* and was rxed by modem */
            {
                ptr = scanstr;          /* reset pointer */
                if(ch == *ptr)          /* and see if its starting over */
                {
                    if(!*++ptr) return(0);
                }
            }
        }
        if(test_kb(number)) return(-1); /* allow exit/back up, if stuck */

        ch = get_com(port);
        if(ch == *ptr)                  /* if a match */
        {
            if(!*++ptr) return(0);      /* inc ptr, return at end of string */
        }
        else                            /* no match */
        {
            if(ch != -1)                /* and was rxed by modem */
            {
                ptr = scanstr;          /* reset pointer */
                if(ch == *ptr)          /* and see if its starting over */
                {
                    if(!*++ptr) return(0);
                }
            }
        }
        if(test_kb(number)) return(-1); /* allow exit/back up, if stuck */

        current = time(NULL);
        if(difftime(current,start) >= 10)
        {
            return(1);
        }
    }
}


int  test_kb(int number)
{
    char chr;

    if(kbhit())                     /* quit on an ESC */
    {
        chr = getch();
        if(chr == 0x1b)  to_exit(number); /* <ESC> to exit the program */
        if(!chr)                    /* check for special char, 00h, */
        {
            chr = getch();
            if(chr == 'I')          /* 00h, 47h is <Pg Up> */
                return(-1);         /* so backup once */
        }
    }
    return(0);
}



void  beep(void)                /* send a short low tone for confirmation */
{
    sound(1000);
    delay(100);
    nosound();
}

void  errbeep(void)             /* send 4 changing tones for ERRORs */
{
    sound(1100);
    delay(200);
    nosound();
    delay(15);                  /* these tones are High-Low, High-Low */

    sound(1000);
    delay(150);
    nosound();
    delay(30);

    sound(1100);                /* it's meant to sound like a British siren */
    delay(200);
    nosound();
    delay(15);

    sound(1000);
    delay(150);
    nosound();
}


char *comment(void)             /* on Errors, allow comment string to be input */
{
    char ch, *ptr;
    int  count;

    printf("\r\nWould you like to enter a comment in the error log(Y or N)? ");
    ptr = cmntptr;
    while(1)
    {
        ch = tolower(getch());          /* see if they want to enter a comment */
        if (ch == 'n')
        {
            putch(ch);                  /* get the response */
            break;                      /* if no just exit */
        }
        else if(ch == 'y')
        {                               /* if Yes, get the comment string */
            printf("Yes\r\n\n");
            count = 0;                  /* zero char input count */
            do
            {
                ch = getch();           /* get a char */
                if((ch == '\b') && count)
                {
                    --cmntptr;          /* allow editing with the backspace */
                    --count;
                    --count;            /* adjust count for edited char */
                    putch(ch);
                    putch(' ');         /* clear character on the screen */
                    putch(ch);
                }
                else if(ch != '\r')     /* normal char are stuffed into buffer */
                {
                    *cmntptr++ = ch;
                    putch(ch);          /* quit on <CR> and at 2000 chars */
                }
            }while((ch != '\r') && (++count < 2000));
            break;
        }
    }
    *cmntptr++ = '\0';                  /* terminate the input */
    return(ptr);                        /* return the beginning address */
}


int  setup_com(int port, int rate, char setup) /* init com1 for rx ints */
{
    char  c;
    int   result;

    disable();                          /* wait */
    outportb(port+lcr,0x80);            /* set DLAB to baud div input */
    outportb(port+1,rate >> 8);         /* set high byte of divisor */
    outportb(port,rate & 0xff);         /* set low byte of divisor */

    outportb(port+lcr,setup);           /* set char attributes */
    if(port == com1)                    /* setup for remote port */
    {
        begin1=end1=0;                  /* set input and output index */
        outportb(port+mcr,0x0B);        /* set RTS and DTR ON permanently */
    }
    else                                /* setup for data port */
    {
        begin2=end2=0;
        outportb(port+mcr,0x09);        /* set DTR permanently ON, RTS is toggled */
    }
    outportb(port+ien,0x01);            /* data available interrupt */
    c = inportb(port);                  /* read any extraneous char */
    c = inportb(ictrlr);                /* read 8259 int enable mask */
    if(port == com1)
    {
        outportb(ictrlr+1,c & intmask1); /* allow com1 interrupts */
    }
    else
    {
        outportb(ictrlr+1,c & intmask2); /* allow com2 interrupts */
    }
    outportb(ictrlr,intrset);           /* reset 8259 */
    enable();                           /* go */
    return(0);
}



int  put_com(int port, char ch, int number)         /* output a char to async */
{
    int  status;
    time_t  start, current;

    start = time(NULL);
    while(!(inportb(port+lsr) & thre))  /* wait until transmitter is empty */
    {
        current = time(NULL);
        if(difftime(current,start) >= 10)
        {
            printf("\r\n ERROR...No Response from COM Port!!");
            return(1);
        }
        if(test_kb(number)) return(-1); /* allow exit/back up, if stuck */
    }
    outportb(port,ch);
    return(0);
}


int  puts_com(int port, char *str, int number)      /* output string of chars to async */
{
    int  result;
    time_t  start, current;

    outportb(port+mcr,0x0B);            /* set RTS ON */
    start = time(NULL);
    while(!(inportb(port+msr) & 0x10))
    {
        current = time(NULL);
        if(difftime(current,start) >= 10)
        {
            printf("\r\n ERROR...No CTS from COM Port!!");
            return(1);
        }
        if(test_kb(number)) return(-1);       /* allow exit/back up, if stuck */
    }
    delay(300);                         /* give time for unit to settle */
    while( *str )
    {
        result = put_com(port, *str,number);
        if(result)  return(result);
        ++str;
    }
    while(!(inportb(port+lsr) & thre))  /* wait for transmitter empty */
        ;
    while(!(inportb(port+lsr) & tsre))  /* wait for shift register empty */
        ;
    delay(1000);
    outportb(port+mcr,0x09);            /* turn RTS OFF */
    return(0);
}


char get_com(int port)               /* read a char from input buffer */
{                                    /* filled by com1 rx interrupt */
    char ch;

    if(port == com1)                 /* com1 */
    {
        if(end1 == begin1) return(-1);
        ch = buf1[begin1];
        begin1 = (begin1 + 1) % bufsiz1;
    }
    else                             /* com2 */
    {
        if(end2 == begin2) return(-1);
        ch = buf2[begin2];
        begin2 = (begin2 + 1) % bufsiz2;
    }
    return(ch);
}


void interrupt comint1(void)     /* read async rx char & stuff in buffer */
{
    int   tmp;

    buf1[end1] = inportb(com1);         /* read the char */
    tmp = (end1 + 1) % bufsiz1;         /* put char in buffer and adjust */
    if(tmp != begin1) end1 = tmp;
    outportb(ictrlr,intrset);           /* resets the int controller */
}


void interrupt comint2(void)     /* read async rx char & stuff in buffer */
{
    int   tmp;

    buf2[end2] = inportb(com2);         /* read the char */
    tmp = (end2 + 1) % bufsiz2;         /* put char in buffer and adjust */
    if(tmp != begin2) end2 = tmp;
    outportb(ictrlr,intrset);           /* resets the int controller */
}


void to_exit(int number)        /* Display results, print and close up shop */
{
    char *ptr, ch;
    int  result, i, type, j;
    struct time  t;
    struct date  d;

    ptr = "c1r1p0\r";           /* return ST-8000A to default parameters on exit */
    while(*ptr)
    {
        result = put_com(com1,*ptr++,number);
        if(result)  break;
    }
    if(number == nbr_instr)     /* if all tests have run display */
    {                           /* congratulations message */
        clrscr();
        printf("%s",congrat);
    }
    printf("\r\n\nPress <Enter> to print the data sheet or <ESC> to exit...");
    do
    {
        ch = toupper(getch());                  /* they should print results */
    }while((ch != 0x1b) && (ch != '\r'));

    if(ch == 0x1b)                              /* if no print, wait for reconfig */
    {
        printf("\r\n\nReconfiguring ST-8000A, please wait...");
        delay(2500);
    }
    else                                        /* print test results */
    {
        printf("\r\n\nPrinting Data Sheet, please wait...");
        fputs(dsheet_head,stdprn);

                                        /* print title, serial # and tech name */
                                        /* do twice for bold face text */

        fprintf(stdprn,"\r                %s",serial);
        fprintf(stdprn,"\r                %s",serial);
        fprintf(stdprn,"\r                                           %s",name);
        fprintf(stdprn,"\r                                           %s",name);

        for(i = 0; i < 32; ++i)         /* for each {log} section print results */
        {
            fputs(dsheet[i],stdprn);
            type = tlog[i].typdata;     /* get the data result type, 0-12 */
            switch(type)
            {
                case 0:
                case 12:  break;        /* 0 and 12 are just <CR> input */

                case 1:
                case 2:
                case 7:                 /* these tests are Y/N or pass/fail */
                case 8:                 /* Y/N is entered from tech,  p/f is */
                case 9:                 /* determined by the program */
                case 11:
                    {
                        if(tlog[i].result)      /* PASS, send twice for BOLD */
                        {
                            fputs(p_msg,stdprn);
                            fputs(p_msg,stdprn);
                        }
                        else                    /* FAIL, send twice for BOLD */
                        {
                            fputs(f_msg,stdprn);
                            fputs(f_msg,stdprn);
                        }
                        break;
                    }

                default:                /* these results are all real numbers input from tech */
                    {                   /* display real numbers in BOLD */

                        fprintf(stdprn,"\r                                            %7.2f",tlog[i].data1);
                        fprintf(stdprn,"\r                                            %7.2f",tlog[i].data1);
                        if(tlog[i].result)
                        {                         /* result calculated in test function */
                            fputs(p_msg,stdprn);
                            fputs(p_msg,stdprn);  /* PASS */
                        }
                        else
                        {
                            fputs(f_msg,stdprn);  /* FAIL */
                            fputs(f_msg,stdprn);
                        }
                    }
            }
            if(!tlog[i].result) break;  /* quit on FAILURES */
        }
        getdate(&d);            /* get the date and time to display */
        gettime(&t);
        fputs(dsheet_tail,stdprn);   /* display final message */
                                     /* and time and date */
        fprintf(stdprn,"\r               %02d-%02d-%02d",d.da_mon,d.da_day,(d.da_year - 1900));
        fprintf(stdprn,"  %02u:%02u ",t.ti_hour,t.ti_min);

        if(i == 32)       /* display the overall PASS result */
        {
            fputs("\r                                                                   P A S S",stdprn);
            fputs("\r                                                                   P A S S",stdprn);
            fputs(dsheet_end,stdprn);
        }
        else              /* display overall FAIL result and failure report */
        {
            fputs("\r                                                                   F A I L",stdprn);
            fputs("\r                                                                   F A I L",stdprn);
            fputs(dsheet_end,stdprn);

            printf("\r\n\nPrinting Failure Report Sheet, please wait... ");


                                   /* display header, serial # and tech name */
            fputs(fsheet1,stdprn);
            fprintf(stdprn,"\r                %s",serial);
            fprintf(stdprn,"\r                %s",serial);
            fprintf(stdprn,"\r                                           %s",name);
            fprintf(stdprn,"\r                                           %s",name);

            fputs(fsheet2,stdprn);  /* display time and date */
            fprintf(stdprn,"\r                        %02d-%02d-%02d",d.da_mon,d.da_day,(d.da_year - 1900));
            fprintf(stdprn,"  %02u:%02u ",t.ti_hour,t.ti_min);

            fputs(fsheet3,stdprn);  /* output column names */
            ptr = tlog[i].comnt;
            while(*ptr)                 /* display comment with underlines */
            {
                fputs(fsheet_line,stdprn);
                fputs("\r  ",stdprn);
                for(j = 0; j < 73; ++j)
                {
                    fputc(*ptr++,stdprn);
                    if(!*ptr) break;
                }
            }
            fputs(fsheet_line,stdprn);  /* one extra line and some empty lines */
            fputs(fsheet_end,stdprn);
        }

    }
    disable();
    bioscom(0,0xE7,0);          /* restore async 1 to non-interrupt driven */
    bioscom(0,0xE7,1);          /* restore async 2 to non-interrupt driven */
    setvect(0x0c,oldasync1);    /* restore old int handler */
    setvect(0x0b,oldasync2);
    enable();                   /* restore interrupts */
    clrscr();                   /* clear the screen */
    printf("%s",fmsg);          /* display factory defaults */
    while(getch() != '\r')      /* get a key when done */
        ;
    exit(0);                    /* bye bye */
}




