/*      Title   All-Pro Diagnostics*/

/******************************************************************************/
/*                                   Diag1                                    */
/*                             All-pro Diagnostic                             */
/*                                                                            */
/* Module ...................... DIAG1                                        */
/* Title ....................... All-pro Diagnostic                           */
/* Developing Engineer ......... George Gruber                                */
/* Company ..................... Logical Devices                              */
/* Revision Level .............. 3.20                                         */
/* Date of Last Revision ....... 19-FEB-86                                    */
/* Last Revision by ............ STH                                          */
/*                                                                            */
/* v2.00        Added read test and slew rate control check for medium and    */
/*              low power drivers.                                            */
/*                                                                            */
/* v3.00        Converted to new allpro                                       */
/*                                                                            */
/* v3.10        Added TTL driver to step pins                                 */
/*                                                                            */
/* v3.20        Added command line echo to file input  STH.                   */
/*                                                                            */
/******************************************************************************/
/*     Subttl  Includes*/
#include <stdio.h>
#include <ctype.h>
#include "cmdfile.h"
#include "pindrivr.h"
/*     Subttl  Defines*/
#define TRUE                            1
#define FALSE                           0

#define MAX_RECORD_LENGTH               135

#define MAX_COMMAND_LENGTH              10                      /* maximum character length of command          */
#define CMD_Q                           0
#define CMD_RESET                       1
#define CMD_STEP                        2
#define CMD_RAMP                        3
#define CMD_SLEW                        4
#define CMD_READ                        5
#define CMD_VOLT                        6
#define CMD_WDAC                        7
#define CMD_WBIT                        8
#define CMD_WPIN                        9
#define CMD_BURN                        10
#define CMD_TEST                        11
#define CMD_PAUSE                       12
#define CMD_STATE                       13
#define CMD_CLOCK                       14
#define CMD_SPIKE                       15
#define CMD_WMEM                        16
#define CMD_TMEM                        17
#define CMD_ADDR                        18
#define CMD_RADDR                       19
#define CMD_COMMENT                     20
#define CMD_RDPINS                      21
#define CMD_RDCUR                       22
#define CMD_WPDAC                       23
#define CMD_HELP                        24
#define MAX_COMMANDS                    25                      /* number of commands in table                  */

#define MAX_PIN_TABLES                  6                       /* number of pin tables (HP, MP, LP, PU and GND)*/
#define MAX_MISC_SYMBOLS                25                      /* number of miscellaneous symbols              */
/*     Subttl  Externals*/
extern pump ();
extern unpump ();
extern udi_write_dac ();
extern udi_write_bit ();
extern udi_write_pin ();
extern write_pin_dac ();
extern udi_burn_bit ();
extern udi_read_bit ();
extern delay_us ();
extern delay_ms ();
/*     Subttl  Variables and Tables*/
unsigned char at_286_flag;

char command_table [MAX_COMMANDS] [MAX_COMMAND_LENGTH + 1] =    /* command list                                 */
{
    { "Q" },
    { "RESET" },
    { "STEP" },
    { "RAMP" },
    { "SLEW" },
    { "READ" },
    { "VOLT" },
    { "WDAC" },
    { "WBIT" },
    { "WPIN" },
    { "BURN" },
    { "TEST" },
    { "PAUSE" },
    { "STATE" },
    { "CLOCK" },
    { "SPIKE" },
    { "WMEM" },
    { "TMEM" },
    { "ADDR" },
    { "RADDR" },
    { "COMMENT" },
    { "RDPINS" },
    { "RDCUR" },
    { "WPDAC" },
    { "?" }
};

char misc_symbol_table [MAX_MISC_SYMBOLS] [20] =                /* miscellaneous symbol name table              */
{
    { "ON" },
    { "OFF" },
    { "SUPPLY1" },
    { "THRESH" },
    { "SLEWRT" },
    { "PUSWIT" },
    { "VPOWER" },
    { "SRC" },
    { "PU" },
    { "GD" }
};

unsigned int misc_symbol_value_table [MAX_MISC_SYMBOLS] =       /* miscellaneous symbol value table             */
{
    ON,
    OFF,
    SUPPLY1_POWER_DAC,
    THRESH_HOLD_DAC,
    SLEW_RATE_DAC,
    PU_CONTROL_DAC,
    DAC_REFERENCE_BIT,
    SRC_DRIVER_ON,
    PU_DRIVER_ON,
    GD_DRIVER_ON
};

int map_20_pin_table [20] =                                     /* 20 pin logical pin to physical pin table     */
{
    11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30
};

    unsigned char left_pin = 182;
    unsigned char right_pin = 199;
    unsigned char top_ic [16]  = {201,205,205,205,205,205,184, 32,213,205,205,205,205,205,187,0};
    unsigned char bott_ic [16] = {200,205,205,205,205,205,205,205,205,205,205,205,205,205,188,0};



int file_cmd_flag = FALSE;                                      /* file input flag                              */

FILE *cmd_file;                                                 /* input input file pointer                     */
int cmd_eof_flag;                                               /* input not end of file flag                   */
char cmd_path [65];                                             /* reserve space to form input filename         */
char cmd_def_ext [] = ".cmd";                                   /* input input file default extension           */
int cmd_line_ctr;                                               /* input line counter                           */
int volt_units;
int volt_tenths;

int vid_mod;
int cursor_top;
int cursor_bottom;
int phys_pin_offset = 0;
int UdiSegment = 0xd000;


char *command_ptr;
char command_buffer [MAX_RECORD_LENGTH + 1];
/*     Subttl  Main*/
main (argc, argv)
int argc;
char *argv [];
{
    unsigned int count;

    for (count = 0; count <= 25; count++)        /* scroll */
    {
        printf ("\n");
    }

    printf ("All-Pro Diagnostics v3.20\n");
    printf ("Enter ? for help, q to quit.\n");

    process_command_tail (argc, argv);                          /* process command line                         */

    pump ();                                                    /* unlock udi interface for access              */

    reset_allpro ();                                            /* initialize all-pro and interface mem map     */

    identify_machine ();                                        /* identify machine running on                  */

    process_commands ();                                        /* enter command processor                      */

    udi_write_bit (DAC_REFERENCE_BIT, OFF);                     /* make sure dac's reference is shut down       */

    unpump ();                                                  /* lock udi interface from access               */
                                                                /* done                                         */
}
/*     Subttl  Determine Machine Type*/
identify_machine ()
{
    unsigned int status;

    unsigned char machine_id;

    machine_id = peek (0xFFFE, 0xF000);

    if (machine_id <= 0xFF && machine_id >= 0xFC)
    {
        if (machine_id == 0xFC)
        {
            at_286_flag = TRUE;
        }
        else
        {
            at_286_flag = FALSE;
        }
    }
    else
    {
        printf ("Unknown PC Macine ID. Enter PC for PC Compatible or AT for AT Compatible");

        get_command_line ();

        string_to_upper (command_buffer);

        if (strncmp ("AT", command_buffer, 2) == 0)
        {
            at_286_flag = TRUE;
        }
        else
        {
            at_286_flag = FALSE;
        }
    }
    get_video_mode ();
    if (vid_mod == 7 || vid_mod == 15)       /*  monochrome  */
    {
        cursor_top = 12;
        cursor_bottom = 13;
    }
    else
    {
        cursor_top = 6;
        cursor_bottom = 7;
    }

}
/*     Subttl  Process Command Line*/
/******************************************************************************/
/* Process command line checks command line tail for a file.  If a file is    */
/* found, it is opened and used for keyboard input until end of file.  The    */
/* command line arguments are argc and argv[] value supplied at main.         */
/*                                                                            */
/* Enter:   fargc               = command line argument count (from main)     */
/*          fargv []            = command line arguments (from main)          */
/*          cmd_def_ext         = input filename default extension            */
/*                                                                            */
/* Call:    process_command_tail (fargc, fargv)                               */
/*                                                                            */
/* Return:  cmd_path            = input file name from fargv [2].  If no      */
/*                              extension was specified, cmd_def_ext was      */
/*                              appended.                                     */
/*          cmd_file            = file handle for input file.  If open for    */
/*                              read fails, program is terminated thru        */
/*                              file_error.                                   */
/******************************************************************************/

process_command_tail (fargc, fargv)                             /* open file.ext and create file.hex            */
int fargc;
char *fargv [];
{
    if (fargc >= 2)                                             /* was two or more filenames given?             */
    {
        build_filename (fargv [1], cmd_path, cmd_def_ext, BFN_APPLY_DEF_EXT); /* build input file           */

        cmd_file = fopen (cmd_path, "r");

        if (cmd_file == NULL)
        {
            printf ("error opening %s", cmd_path);            /* error opening input file, exit               */
            exit (1);
        }

        cmd_line_ctr = 0;                                       /* reset line counter                           */
        cmd_eof_flag = 1;                                       /* reset input end of file flag                 */
        file_cmd_flag = TRUE;                                   /* file input flag                              */
    }
}
/*     Subttl  Process User Commands*/
/******************************************************************************/
/* Process user commands.  Prompts user for single line command and breaks    */
/* command down into command and arguments and then  dispatches to a routine  */
/* to execute command.                                                        */
/******************************************************************************/

process_commands ()
{
    int command_type;
    int cmd_arg_ctr;
    int cmd_arg_table [5];
    int arg_ctr;

    char command_name [MAX_COMMAND_LENGTH + 1];

    command_type = 1;

    while (command_type != 0)
    {
        get_command_line ();                                    /* read command line                            */

        get_command (command_name);                             /* get command name from command line           */


        for (arg_ctr = 0; arg_ctr < 5; arg_ctr++)
        {
            cmd_arg_table [arg_ctr] = 0;
        }

        for (cmd_arg_ctr = 0; (*command_ptr != '\0') && (*command_ptr != ';'); cmd_arg_ctr++)
        {
            if ((cmd_arg_table [cmd_arg_ctr] = get_argument ()) == -1) /* get a command argument                    */
            {
                command_error ("illegal agrument in command line", "");
                break;
            }
        }

        if ((strlen (command_name) != 0) && (cmd_arg_table [cmd_arg_ctr] != -1))
        {
            string_to_upper (command_name);

            for (command_type = 0; command_type < MAX_COMMANDS && (strcmp (command_name, command_table [command_type]) != 0); command_type++)
            {
            }

            if (command_type < MAX_COMMANDS)
            {
                dispatch_command (command_type, cmd_arg_ctr, cmd_arg_table);
            }
            else
            {
                command_error ("undefined command ", command_name);
            }
        }
    }
}
/*     Subttl  Get Command Field from Input Line*/
/******************************************************************************/
/* Get command from input line.  Bypasses any leading white spaces, copies the*/
/* string upto the next white space and continues until next non-white space  */
/* is found leaving ptr positioned at start of an argument or end of line.    */
/*                                                                            */
/* Enter:   data_field_ptr      = ptr to where string should be built         */
/*                                                                            */
/* Call:    get_command (data_field_ptr)                                      */
/*                                                                            */
/* Return:  data_field_ptr      = with null terminated string                 */
/*          *command_ptr        = pointing to start of next non-blank  or end */
/*                              of line                                       */
/******************************************************************************/

get_command (data_field_ptr)
char *data_field_ptr;
{
    int field_ctr;

    while ((*command_ptr <= ' ') && *command_ptr)
    {
        *command_ptr++;
    }

    for (field_ctr = 0; (field_ctr <= MAX_COMMAND_LENGTH) && (*command_ptr > ' '); field_ctr++)
    {
        *data_field_ptr++ = *command_ptr++;
    }

    *data_field_ptr = '\0';

    while ((*command_ptr <= ' ') && *command_ptr)
    {
        *command_ptr++;
    }
}
/*     Subttl  Get an Argument from the Input Line*/
get_argument ()
{
    int arg_value;

    char *symbol_ptr;
    char symbol_buffer [11];

    arg_value = 0;

    if (*command_ptr == '$')
    {
        *command_ptr++;

        while ((isxdigit (*command_ptr)) && (arg_value != -1))
        {
            arg_value *= 16;

            if (*command_ptr > '9')
            {
                arg_value = arg_value + ((toupper (*command_ptr++)) - ('A' - 10));
            }
            else
            {
                arg_value = arg_value + ((*command_ptr++) - '0');
            }
        }
    }
    else
    {
        if (isdigit (*command_ptr))
        {
            while (isdigit (*command_ptr) && (arg_value != -1))
            {
                arg_value = (arg_value * 10) + ((*command_ptr++) - '0');
            }
        }
        else
        {
            symbol_ptr = symbol_buffer;

            while (isalnum (*command_ptr))
            {
                *symbol_ptr++ = *command_ptr++;
            }

            *symbol_ptr = '\0';

            string_to_upper (symbol_buffer);

            arg_value = lookup_symbol (symbol_buffer);
        }
    }

    while (((*command_ptr <= ' ') || (*command_ptr == ',')) && (*command_ptr != 0))
    {
        *command_ptr++;
    }

    return (arg_value);
}
/*     Subttl  Lookup Symbol and Convert to Value*/
lookup_symbol (sym_ptr)
char *sym_ptr;
{
    int pin;
    int sym_value;
    int sym_offset;

    char sub_sym [3];
    char *sub_sym_ptr;

    for (sym_offset = 0; (sym_offset < MAX_MISC_SYMBOLS) && (strcmp (sym_ptr, misc_symbol_table [sym_offset]) != 0); sym_offset++)
    {
    }

    if (sym_offset < MAX_MISC_SYMBOLS)
    {
        sym_value = misc_symbol_value_table [sym_offset];
    }
    else
    {
        sym_value = -1;
    }

    return (sym_value);
}
/*     Subttl  Dispatch Command*/
dispatch_command (command, arg_ctr, arg_ptr)
int command;
int arg_ctr;
int *arg_ptr;
{
    switch (command)
    {
        case CMD_Q:
        {
            break;
        }

        case CMD_RESET:
        {
            reset_allpro ();
            break;
        }

        case CMD_STEP:
        {
            if (arg_ctr < 2)
                {
                    arg_ptr [1] = arg_ptr [0];
                }

            step_pin (arg_ptr [0], arg_ptr [1]);
            break;
        }

        case CMD_RAMP:
        {
            if (arg_ctr < 2)
                {
                    arg_ptr [1] = arg_ptr [0];
                }

            hi_med_pin_test (arg_ptr [0], arg_ptr [1]);
            break;
        }

        case CMD_SLEW:
        {
            slew_rate_test (arg_ptr [0], arg_ptr [1]);
            break;
        }

        case CMD_READ:
        {
            read_udi_byte (arg_ptr [0]);
            break;
        }

        case CMD_RDCUR:
        {
            printf ("\n %4d ma", read_current () );
            break;
        }

        case CMD_VOLT:
        {
            while (keyboard_status () == -1)
            {
                volt_units = read_pin_voltage (arg_ptr [0]) / 10;
                volt_tenths = volt_units % 10;
                volt_units /= 10;
                printf ("pin %d = %2d.%1d volts\r", arg_ptr [0], volt_units, volt_tenths );
            }

            break;
        }

        case CMD_WDAC:
        {
            udi_write_dac (arg_ptr [0], arg_ptr [1]);

            break;
        }

        case CMD_WPDAC:
        {
            set_pin_dac (arg_ptr [0], arg_ptr [1]);

            break;
        }

        case CMD_WBIT:
        {
            udi_write_bit (arg_ptr [0], arg_ptr [1]);

            break;
        }

        case CMD_WPIN:
        {
            udi_write_pin (arg_ptr [0] | arg_ptr [1]);

            break;
        }

        case CMD_BURN:
        {
            if (arg_ctr < 2)
            {
                arg_ptr [1] = arg_ptr [0];
            }

            if (arg_ctr < 3)
            {
                arg_ptr [2] = 30;
            }

            if (arg_ctr < 4)
            {
                arg_ptr [3] = 8;
            }

            break;
        }

        case CMD_TEST:
        {
            if (arg_ctr < 2)
            {
                arg_ptr [1] = arg_ptr [0];
            }

            if (arg_ctr < 3)
            {
                arg_ptr [2] = 30;
            }

            if (arg_ctr < 4)
            {
                arg_ptr [3] = 8;
            }

            while (keyboard_status () == -1)
            {
                delay_us ((arg_ptr [2] + (arg_ptr [3] * 4)) * 10);
            }

            break;
        }

        case CMD_PAUSE:
        {
            printf ("paused for operator");

            while (keyboard_status () == -1)
            {
            }

            printf ("\n");
            break;
        }

        case CMD_STATE:
        {
            if (read_pin_state (arg_ptr [0]))
            {
                printf ("1");
            }
            else
            {
                printf ("0");
            }

            break;
        }

        case CMD_CLOCK:
        {
            if (arg_ctr < 2)
            {
                arg_ptr [1] = 0;
            }

            while (keyboard_status () == -1)
            {
                udi_clock_pin (arg_ptr [0], arg_ptr [1]);
            }

            break;
        }

        case CMD_SPIKE:
        {
            if (arg_ctr < 3)
            {
                arg_ptr [2] = arg_ptr [1];
            }

            spike_test (arg_ptr [0], arg_ptr [1], arg_ptr [2]);

            break;
        }

        case CMD_WMEM:
        {
            udi_write_mem (arg_ptr [0], arg_ptr [1]);
            break;
        }

        case CMD_TMEM:
        {
            while (keyboard_status () == -1)
            {
                udi_write_mem (arg_ptr [0], arg_ptr [1]);
            }

            break;
        }

        case CMD_ADDR:
        {
            if (arg_ctr < 4)
            {
                if (arg_ctr < 3)
                {
                    if (arg_ctr < 2)
                    {
                        arg_ptr [2] = 0;
                    }

                    arg_ptr [3] = arg_ptr [2];
                }

                arg_ptr [1] = arg_ptr [0];
            }

            test_address (arg_ptr [0], arg_ptr [1], arg_ptr [2], arg_ptr [3]);

            break;
        }

        case CMD_RADDR:
        {
            test_rotate_address ();

            break;
        }

        case CMD_COMMENT:
        {
            break;
        }

        case CMD_RDPINS:
        {
            calibrate_pins ( arg_ptr [0] );
/*            open_pins_test ();*/

            break;
        }

        case CMD_HELP:
        {
            display_help ();

            break;
        }

        default:
        {
            command_error ("un-implemented command ", command_table [command]);
        }
    }
}
/*     Subttl  Initialize All-Pro*/
reset_allpro ()
{
    int pin;                                                    /* pin counter to reset pins                    */
    int *pin_table_ptr;

    udi_write_bit (DAC_REFERENCE_BIT, OFF);                     /* make sure vcc power is shut down             */
    udi_write_dac (SUPPLY1_POWER_DAC, 0);                       /* high power dac to 0 volts                    */
    udi_write_dac (THRESH_HOLD_DAC, 0);

    for (pin = 1; pin <= 48; pin++)
    {
        udi_write_pin (pin | 0);                                /* make sure all drivers are off                */
        write_pin_dac (pin, 0);
    }
}

/*     Subttl  calabrate pins */
/******************************************************************************/
/*                                                                            */
/* Call:    calibrate_pins ()                                                 */
/*                                                                            */
/* Return:  display pin voltages                                              */
/******************************************************************************/

calibrate_pins( voltage )
int voltage;
{
    int pin;
    int test_count;
    int break_status;
    int row;
    int col;
    int page;
    int volt_table [40] [13];
    unsigned long volt_acc [40];
    int pass;
    unsigned int temp;
    unsigned int pass_number;

    reset_allpro();
    udi_write_bit (DAC_REFERENCE_BIT, ON);                      /* make sure dac reference on                   */
    udi_write_dac (SLEW_RATE_DAC, 100);                         /* use maximum slew                             */
    udi_write_dac (PU_CONTROL_DAC, 600);

    delay_ms (400);                                             /* allow switchers to come up to power          */

    crt_cursor_type (15,15);

    if ( voltage )
    {
        for ( pin = 5; pin <= 44; pin++)
        {
            udi_write_pin (pin | SRC_DRIVER_ON);
            write_pin_dac ( pin, (voltage * 10) + 80);
            udi_write_dac (SUPPLY1_POWER_DAC, voltage * 10);                    /* initialize all power dacs                    */
        }
    }
    else
    {
        for ( pin = 5; pin <= 44; pin++)
        {
            udi_write_pin (pin | SRC_DRIVER_ON);
            write_pin_dac ( pin, (pin) * 50 + 80);
            udi_write_dac (SUPPLY1_POWER_DAC, 2500);                    /* initialize all power dacs                    */
        }
    }


    for ( row = 1; row < 26; row++)
    {
        printf ("\n");
    }

    page = 0;
    crt_pos_cursor ( 1, 34, page );
    printf ("%s", top_ic);

    row = 2;
    for ( pin = 5; pin <= 24; pin++ )
    {
        crt_pos_cursor ( row, 34, page);
        printf ("%c %2d       %2d %c", left_pin, pin, 49 - pin , right_pin  );
        row++;
    }

    crt_pos_cursor (22, 34, page );
    printf ("%s", bott_ic);

    for ( pin = 0; pin < 40; pin++ )
    {
        volt_table [pin] [11] = read_pin_voltage (pin + 5) / 10;
        volt_table [pin] [12] = volt_table [pin] [11];
        volt_acc [pin] = 0;
    }

    break_status = FALSE;                          /* check keyboard status for break              */
    pass_number = 0;

    while (break_status == FALSE)
    {


    /*  read voltage at all pins 10 times and store in array   */

        for ( pin = 0; pin < 40 && break_status == FALSE; pin++ )
        {
            for (pass = 1; (pass <= 10) && (break_status == FALSE); pass++)
            {
                temp = read_pin_voltage (pin + 5) / 10;
                volt_acc [pin] += (long) temp;
                if ( temp > volt_table [pin] [11] )
                {
                    volt_table [pin] [11] = temp;
                }
                if ( temp < volt_table [pin] [12] )
                {
                    volt_table [pin] [12] = temp;
                }

                if ( keyboard_status () != -1 )
                {
                    break_status = TRUE;
                }
            }
            volt_table [pin] [10] = (int) (volt_acc [pin] / (pass_number + 10) );
        }

    /*  print all voltages around IC  */
        crt_pos_cursor ( 1, 1, 0 );
        pass_number += 10;
        printf ("Pass %5d", pass_number );
        for (row = 1; row <= 20 && break_status == FALSE; row++)
        {
            crt_pos_cursor ( row + 1, 13, page );
            if ( volt_table [row-1] [10] < 255 )
            {
                printf ("+%02d.%01d  -%02d.%01d   %2d.%1d",
                       (volt_table [row-1] [11] - volt_table [row-1] [10]) / 10,
                       (volt_table [row-1] [11] - volt_table [row-1] [10]) % 10,
                       (volt_table [row-1] [10] - volt_table [row-1] [12]) / 10,
                       (volt_table [row-1] [10] - volt_table [row-1] [12]) % 10,
                       volt_table [row-1] [10] / 10,
                       volt_table [row-1] [10] % 10);
                if ((volt_table [row-1] [11] - volt_table [row-1] [12]) > 4 )
                {
                    crt_pos_cursor ( row + 1, 38, page);
                    printf ("*");

                }
            }
            crt_pos_cursor ( row + 1, 51, page );
            if ( volt_table [40-row] [10] < 255 )
            {
                printf ("%2d.%1d   +%02d.%01d  -%02d.%01d",
                       volt_table [40-row] [10] / 10,
                       volt_table [40-row] [10] % 10,
                       (volt_table [40-row] [11] - volt_table [40-row] [10]) / 10,
                       (volt_table [40-row] [11] - volt_table [40-row] [10]) % 10,
                       (volt_table [40-row] [10] - volt_table [40-row] [12]) / 10,
                       (volt_table [40-row] [10] - volt_table [40-row] [12]) % 10 );
                if ((volt_table [40-row] [11] - volt_table [40-row] [12]) > 4 )
                {
                    crt_pos_cursor ( row+1, 44, page);
                    printf ("*");

                }
            }
            if ( keyboard_status () != -1 )
            {
                break_status = TRUE;
            }
        }

    }
    udi_write_dac (SUPPLY1_POWER_DAC, 0);                       /* shut down all power dacs                     */
    udi_write_bit (DAC_REFERENCE_BIT, OFF);                     /* make sure dac reference is shut down         */
    crt_pos_cursor ( 23,1,0);
    crt_cursor_type ( cursor_top, cursor_bottom );
}







/*     Subttl  Step Pin Test*/
/******************************************************************************/
/* Step pin thru all of its seperate pin drivers.  This will use different    */
/* voltages (described below) for each of the pin drivers.  It will also      */
/* enable the next pin driver before shutting off the previous pin.  The      */
/* sequencing and voltages  are as follows:                                   */
/* high power           18 volts with current slew                            */
/* medium power         14 volts with current slew                            */
/* low power            10 volts                                              */
/* pull-up              5 volts                                               */
/* ground driver        0 volts                                               */
/*                                                                            */
/* Note: slew rate is set for maximum slew.                                   */
/*                                                                            */
/* This stepping occurs at the best speed possible from CPU.                  */
/*                                                                            */
/* Enter:   start_pin           = starting pin number to step                 */
/*          end_pin             = last pin number to step                     */
/*                                                                            */
/* Call:    step_pin (start_pin, end_pin)                                     */
/*                                                                            */
/* Return:  pin(s) stepped, (no returned value)                               */
/******************************************************************************/

step_pin (start_pin, end_pin)
int start_pin;
int end_pin;
{
    int pin;
    int test_count;
    int break_status;

    udi_write_bit (DAC_REFERENCE_BIT, ON);                      /* make sure dac reference on                   */
    udi_write_dac (SLEW_RATE_DAC, 100);                         /* use maximum slew                             */
    udi_write_dac (SUPPLY1_POWER_DAC, 2550);                    /* initialize all power dacs                    */
    udi_write_dac (PU_CONTROL_DAC, 500);

    delay_ms (400);                                             /* allow switchers to come up to power          */

    break_status = keyboard_status ();                          /* check keyboard status for break              */

    while (break_status == -1)
    {
        for (pin = start_pin; (pin <= end_pin) && ((break_status = keyboard_status ()) == -1); pin++)
        {
            udi_write_dac (PU_CONTROL_DAC, 1000 );
            write_pin_dac (pin, 2200);
            delay_ms (2);

            udi_write_pin (pin | SRC_DRIVER_ON);                 /* start sequencing                   */
            udi_write_pin (pin | PU_DRIVER_ON);
            udi_write_pin (pin | GD_DRIVER_ON | PU_DRIVER_ON);
            udi_write_pin (pin | TTL_DRIVER_ON);
            udi_write_pin (pin | DISCONNECT);                    /* check for decouple driver stuck    */

            write_pin_dac (pin, 00);
            udi_write_dac (PU_CONTROL_DAC, 00 );
            udi_write_pin (pin | SRC_DRIVER_ON);                 /* start sequencing                   */
            udi_write_dac (SLEW_RATE_DAC,00);
            write_pin_dac (pin, 1200);
            write_pin_dac (pin, 1200);
            write_pin_dac (pin, 1200);
            udi_write_pin (pin | PU_DRIVER_ON);
            udi_write_dac (PU_CONTROL_DAC, 1200 );
            write_pin_dac (pin, 00);
            write_pin_dac (pin, 00);
            write_pin_dac (pin, 00);

            udi_write_pin (pin | GD_DRIVER_ON);
            udi_write_dac (PU_CONTROL_DAC, 00 );
            udi_write_pin (pin | 0);                            /* all pin drivers off                          */
            write_pin_dac (pin, 0);
            udi_write_dac (SLEW_RATE_DAC,100);
        }
    }

    udi_write_dac (SUPPLY1_POWER_DAC, 0);                       /* shut down all power dacs                     */
    udi_write_bit (DAC_REFERENCE_BIT, OFF);                     /* make sure dac reference is shut down         */
}
/*     Subttl  High / Medium Power Pin Test*/
/******************************************************************************/
/* Test high power and medium power pin drivers.  This will use different     */
/* voltages (described below) for each of the pin drivers.  This will turn    */
/* on the switches of the high and medium pins and toggle the enable pins.    */
/* The sequencing and voltages are as follows:                                */
/* high power           18 volts with current slew                            */
/* medium power         14 volts with current slew                            */
/* low power            10 volts                                              */
/* pull-up              5 volts                                               */
/* ground driver        0 volts                                               */
/*                                                                            */
/* Note: slew rate is set for maximum slew.                                   */
/*                                                                            */
/* This stepping occurs at the best speed possible from CPU.                  */
/*                                                                            */
/* Enter:   pin                 = pin number to step                          */
/*                                                                            */
/* Call:    step_pin (pin)                                                    */
/*                                                                            */
/* Return:  nothing                                                           */
/******************************************************************************/

hi_med_pin_test (start_pin, end_pin)
int start_pin;
int end_pin;
{
    int pin;
    int test_count;
    int break_status;

    udi_write_bit (DAC_REFERENCE_BIT, ON);                      /* make sure dac reference on                   */
    udi_write_dac (SLEW_RATE_DAC, 2550);                        /* use maximum slew                             */
    udi_write_dac (SUPPLY1_POWER_DAC, 1800);                    /* initialize all power dacs                    */


    for (pin = start_pin; (pin <= end_pin) && ((break_status = keyboard_status ()) == -1); pin++)
    {
        write_pin_dac (pin, 1800);
    }

    delay_ms (400);                                             /* allow switchers to come up to power          */

    break_status = keyboard_status ();                          /* check keyboard status for break              */

    while (break_status == -1)
    {
        for (pin = start_pin; (pin <= end_pin) && ((break_status = keyboard_status ()) == -1); pin++)
        {
            udi_write_pin (pin | SRC_DRIVER_ON);                 /* start sequencing                             */
            udi_write_pin (pin | PU_DRIVER_ON);
            udi_write_pin (pin | GD_DRIVER_ON);
            udi_write_pin (pin | 0);
        }
    }

    udi_write_dac (PU_CONTROL_DAC, 0);
    udi_write_dac (SUPPLY1_POWER_DAC, 0);                       /* initialize all power dacs                    */
    udi_write_dac (SLEW_RATE_DAC, 0);                           /* use maximum slew                             */
    udi_write_bit (DAC_REFERENCE_BIT, OFF);                     /* make sure dac reference on                   */
}
/*     Subttl  Spike Test*/
spike_test (voltage, start_pin, end_pin)
int voltage;
int start_pin;
int end_pin;
{
}
/*     Subttl  Slew Rate Test*/
/******************************************************************************/
/* Slew medium and low power pin with the given value.                        */
/* Medium driver will be set to 15 V.                                         */
/* Low driver will be set to 10 V.                                            */
/*                                                                            */
/*                                                                            */
/* Enter:   pin_address         = high power pin number to step               */
/*          slew_rate           = slew rate value for slew rate DAC           */
/*                                                                            */
/* Call:    slew_rate_pin (pin_address, slew_rate)                            */
/*                                                                            */
/* Return:  nothing                                                           */
/******************************************************************************/

slew_rate_test (pin_address, slew_rate)
int pin_address;
int slew_rate;
{
    udi_write_bit (DAC_REFERENCE_BIT, ON);                      /* make sure dac reference on                   */
    udi_write_dac (SLEW_RATE_DAC, slew_rate);
    udi_write_dac (SUPPLY1_POWER_DAC, 1500);

    delay_ms (400);                                             /* allow switchers to come up to power          */

    while (keyboard_status () == -1)
    {
        delay_us (300);
        udi_write_pin (pin_address | SRC_DRIVER_ON);            /* start sequencing                   */
        write_pin_dac (pin_address, 1500);                              /* turn medium power to 15 V */
        delay_us (50);                                          /* give time to rise and sync */
        write_pin_dac (pin_address, 0);                                 /* turn medium power switch off */
        delay_us (50);

    }

    udi_write_pin (pin_address, OFF);
    udi_write_dac (SUPPLY1_POWER_DAC, 0);
    udi_write_bit (DAC_REFERENCE_BIT, OFF);                     /* make sure dac reference is shut down         */
}
/*     Subttl  Read All-Pro Device Register*/
/******************************************************************************/
/* Read all-pro device register.  Reads byte from specified address of device */
/* and also from the memory map table.  This allows read back of write only   */
/* pins.                                                                      */
/*                                                                            */
/* Enter:   dev_address         = device / memory address to read             */
/*                                                                            */
/* Call:    read_udi_byte (dev_address)                                       */
/*                                                                            */
/* Return:  displays the hex value of device data and memory map data         */
/******************************************************************************/

read_udi_byte (dev_address)
unsigned int dev_address;
{
}

read_20_pin_pal ()
{
    udi_write_dac (SLEW_RATE_DAC, 1280);                        /* setup slew rate for approx 1.5 V/uS          */
    udi_write_dac (SUPPLY1_POWER_DAC, 500);                     /* use high power for Vcc                       */
}
/*     Subttl  Read Current*/
/******************************************************************************/
/* Read universal device current level.  This performs a successive           */
/* approximation on the current. The threshold DAC is initially set to the    */
/* mid-point value and then the bit is read from the comparator. If this      */
/* value is a one, one half of the last guess is added to the guess other-    */
/* wise, one half of the last guess is subtracted from the last guess.  The   */
/* new last guess is used as the new value for the threshold DAC and is       */
/* repeated until the last guess offset is zero.  This value of the approx-   */
/* imation is return.                                                         */
/*                                                                            */
/* Enter:                                                                     */
/*                                                                            */
/* Call:    read_current ()                                                   */
/*                                                                            */
/* Return:  approximate current level into the source drivers                 */
/******************************************************************************/

read_current ()
{
    unsigned int approx;
    unsigned int guess;

    approx = 0;                                                 /* initial approximation                        */

    for (guess = 0x80; guess > 0; guess >>= 1)                  /* addend and control                           */
    {
        udi_write_mem (CURRENT_DAC, approx + guess);            /* set comp drive                               */

        if (udi_read_ovc ())                                    /* was it too low?                              */
        {
            approx = approx + guess;                            /* yes - restore AND add                        */
        }
    }
    return (approx * 9);                                        /* return pinvalue                              */
}
/*     Subttl  Read Pin Voltage*/
/******************************************************************************/
/* Read universal device pin voltage.  This performs a successive             */
/* approximation upon the pin.  The threshold DAC is initially set to the     */
/* mid-point value and then the pin is read from the specified pin.  The pin  */
/* number is used as a reference into the read_pin_table to derive the mask   */
/* and device address and the pin is read and ANDed with its mask. If this    */
/* value is a one, one half of the last guess is added to the guess other-    */
/* wise, one half of the last guess is subtracted from the last guess.  The   */
/* new last guess is used as the new value for the threshold DAC and is       */
/* repeated until the last guess offset is zero.  This value of the approx-   */
/* imation is return.                                                         */
/*                                                                            */
/* Enter:   pin                 = pin number to read                          */
/*                                                                            */
/* Call:    read_pin_voltage (pin)                                            */
/*                                                                            */
/* Return:  approximate voltage of the specified pin                          */
/******************************************************************************/

read_pin_voltage (pin)
unsigned int pin;
{
    unsigned int approx;
    unsigned int guess;

    approx = 0;                                                 /* initial approximation                        */

    for (guess = 0x80; guess > 0; guess >>= 1)                  /* addend and control                           */
    {
        udi_write_mem (THRESH_HOLD_DAC, approx + guess);        /* set comp drive                               */

        if (udi_read_bit (pin))                                 /* was it too low?                              */
        {
            approx = approx + guess;                            /* yes - restore AND add                        */
        }
    }

    return (approx * 10);                                       /* return pinvalue                              */
}
/*     Subttl  Read Pin State*/
/******************************************************************************/
/* Read universal device bit state.  Sets the threshold DAC to 2.5 volts and  */
/* then reads the pin (which is used as an offset into read_pin_table to      */
/* obtain the device bit mask and device address).  The device register is    */
/* read and then ANDed with the bit mask.  This value is then returned (i.e   */
/* either zero if the bit wasn't set or non-zero if the bit was set).         */
/*                                                                            */
/* Enter:   pin                 = pin number to read state from               */
/*                                                                            */
/* Call:    read_pin_state (pin)                                              */
/*                                                                            */
/* Return:  state of the pin with reference to 2.5 volts                      */
/******************************************************************************/

read_pin_state (pin)
unsigned int pin;
{
    udi_write_dac (THRESH_HOLD_DAC, 250);
    return (udi_read_bit (pin));
}
/*     Subttl  Test Address*/
test_address (start_address, end_address, start_data, end_data)
unsigned int start_address;
unsigned int end_address;
unsigned int start_data;
unsigned int end_data;

{
    unsigned int address;
    unsigned char data;

    while (keyboard_status () == -1)
    {
        for (address = start_address; address <= end_address; address++)
        {
            for (data = start_data; data <= end_data; data++)
            {
                udi_write_mem (address, data);
            }
        }
    }
}
/*     Subttl  Rotate Address Test*/
test_rotate_address ()

{
    unsigned int address;
    unsigned int data;

    while (keyboard_status () == -1)
    {
        for (address = 0x0001; address <= 0x1000; address <<= 1)
        {
            for (data = 0x01; data <= 0x80; data <<=1)
            {
                udi_write_mem (address, data);
            }
        }
    }
}

/*     Subttl  Open Pins Test */
open_pins_test ()

{
    unsigned int pin;
    unsigned int okstatus;
    unsigned int pin_voltage;

    okstatus = TRUE;

    udi_write_bit (DAC_REFERENCE_BIT, ON);                      /* make sure dac reference on                   */

    for (pin = 5; pin <= 44; pin++)
    {
        if (pin_voltage = read_pin_voltage (pin)) /* if pin voltage is non-zero, display pin number */
        {
            pin_voltage /= 10;
            volt_units = pin_voltage / 10;
            volt_tenths = pin_voltage % 10;
            printf ("Pin %2d = %2d.%1d volts\n", pin, volt_units, volt_tenths );
            okstatus = FALSE;
        }
    }

    if (okstatus)
    {
        printf ("\nPins are connected to the interface card.\n");
    }
    else
    {
        printf ("\nFix the problems with the displayed pin(s).\n");
    }

    udi_write_bit (DAC_REFERENCE_BIT, OFF);                      /* make sure dac reference is off */
}

/*     Subttl  Get Command Line*/
/******************************************************************************/
/* Get command line gets a line for the command line processor.  It will read */
/* a line from an input file if file_cmd_flag is TRUE or prompts the user     */
/* with a prompt and waits for a line from STDIN.  The input line is limited  */
/* to MAX_RECORD_LENGTH, with data always being written to command_buffer and */
/* the line is always NULL terminated.  The reason for using fgets (,,stdin)  */
/* is because of the command line editing support from DOS.                   */
/*                                                                            */
/* Enter:   file_cmd_flag       = TRUE to read a line from a file or FALSE if */
/*                              to prompt user and wait for line from STDIN   */
/*                                                                            */
/* Call:    get_command_line ()                                               */
/*                                                                            */
/* Return:  command_buffer      = NULL terminated string not exceeding        */
/*                              MAX_RECORD_LENGTH                             */
/******************************************************************************/

get_command_line ()
{
    if (file_cmd_flag)
    {
        if (!(cmd_eof_flag))
        {
            printf ("unexpected end of file %s", cmd_path);   /* yes, file error, unexpected end of file      */
            exit (1);
        }

        if ((fgets (command_buffer, MAX_RECORD_LENGTH, cmd_file)) != 0)
        {
            printf ("%s\n", command_buffer);
            cmd_line_ctr++;
        }
        else
        {
            printf ("\nfinished reading %s\n", cmd_path);
            file_cmd_flag = FALSE;
            fclose (cmd_file);
        }
    }
    else
    {
        printf ("\napd>");                                      /* command prompt                               */
        fgets (command_buffer, MAX_RECORD_LENGTH, stdin);       /* read command line from user                  */

        get_analog_id ();
    }

        command_ptr = command_buffer;
}
/*     Subttl  Display Command Error*/
command_error (cmd_error_message, cmd_string)
char *cmd_error_message;
char *cmd_string;
{
    printf ("\naprodiag.c: ");
    printf (&*cmd_error_message);
    printf (&*cmd_string);

    if (file_cmd_flag)
    {
        printf (" in file %s, at line %d", cmd_path, cmd_line_ctr);
    }
}
/*      Subttl  Help Display */
display_help ()
{
    unsigned int count;

    for (count = 0; count <= 25; count++)        /* scroll */
    {
        printf ("\n");
    }
    printf ("                               Diagnostics Commands\n\n");
    printf ("      wbit vpower on  -  Turn on the dac reference voltage.\n");
    printf ("      wmem $ val      -  Write specified value to specified dac address.\n");
    printf ("      wpin # driver   -  Turn on the specified driver of specified pin.\n");
    printf ("      wpdac # volts   -  Write the specified pin driver dac.\n");
    printf ("      slew # val      -  Slew medium and low power of specified pin.\n");
    printf ("      step #          -  Step waveform applied to the specified pin.\n");
    printf ("      step range      -  Step waveform applied to the specified range of pins.\n");
    printf ("      raddr           -  Apply a rotating bit on the data and address busses.\n");
    printf ("      rdpins [volts]  -  Check all pins for connection.\n");
    printf ("      rdcur           -  Read current level.\n");
    printf ("      volt #          -  Read voltage on specified pin.\n");
    printf ("      q               -  Quit the diagnostics.\n");
    printf ("      ?               -  Show this screen.\n\n\n");
    printf ("      where:        # = [5, 6, 7, ..., 44]\n");
    printf ("                  val = [0 - 255]\n");
    printf ("               driver = [SRC, PU, GD, TTL]\n");
    printf ("                range = [start pin - end pin]\n");
    printf ("                    $ = [SUPPLY1, THRESH, SLEWRT, PUSWIT\n\n");
}

get_video_mode ()
{
    struct intstruc
    {   int     AX;
        int     BX;
        int     CX;
        int     DX;
        int     SI;
        int     DI;
        int     DS;
        int     ES;
    }
    intcall;
    intcall.AX = 0x0f00;
    sysint (0x10,(struct intstruc *) &intcall,(struct intstruc *) &intcall);
    vid_mod = (intcall.AX & 0x00ff);
}
