/*	Title	Global Data*/
/******************************************************************************/
/*				    Diag3				      */
/*			      Allpro diagnostic 3			      */
/*									      */
/* Project .................... Allpro - Universal Programmer		      */
/* Module ..................... DIAG3.C 				      */
/* Title ...................... Allpro diagnostic 3			      */
/* Developing Engineer ........ Steven T. Harr				      */
/* Company .................... Logical Devices 			      */
/* Revision Level ............. v3.00					      */
/* Date of Last Revision ...... 01-02-90				      */
/* Last Revision by ........... STH					      */
/* Developing System .......... IBM PC or compatible			      */
/* Target System .............. IBM PC or compatible			      */
/* Language ................... C					      */
/* Compiler ................... Manx Aztec C v3.20e			      */
/* Compiler Command(s) ........ cc Diag3				      */
/*									      */
/* Interpreter ................ none					      */
/*									      */
/* Synopsis ................... This module contains the MAIN entrance	      */
/*				point and the main menu.		      */
/*									      */
/* Revision History:							      */
/*  v3.00   10-16-89		Original version - STH			      */
/*				Converted from diag2 to use allpro menus.     */
/*									      */
/*									      */
/******************************************************************************/
/*	Subttl	Includes    */
#include <stdio.h>
#include <ctype.h>
#include "cmdfile.h"
#include "pindrivr.h"
#include "keybrd.h"
#include "diag2.h"
#include "windows.h"
#include "window.h"


/*	Subttl	Equates    */
#define TRUE				1
#define FALSE				0
#define MAX_DEPTH			8

#define REVERSE_VIDEO			0x70
#define NORMAL_VIDEO			0x07
#define INTENSIFY_VIDEO 		0x08

#define MENU_OFF			0x01

/*     Subttl  Externals*/
extern char revision_level [];
extern char cwd_path [];
extern char command_buffer [];
extern struct window_def_struc status_window_table [];
extern struct window_usage_struc status_display_table [];
/*
extern struct window_def_struc *win_table;
extern struct window_usage_struc *dis_table;
*/
#define win_table   status_window_table
#define dis_table   status_display_table


/*     Subttl  Variables and Tables*/

unsigned char at_286_flag;
unsigned int se6440_flag;
unsigned int allpro88_flag;
unsigned int UdiSegment = 0xa000;   /* default segment */
unsigned int max_pins;
int vid_mod;
int cursor_top;
int cursor_bottom;
int highlight_width;

int func_null ();
int func_analog_cont ();
int func_pin_driver_test ();
int func_help ();
int func_trblsht ();
int func_edit ();
int func_config ();
int func_ibmint ();
int func_controller();
/*int func_se6440();*/
int show_system_info();
int func_system_test();
int show_pin_driver_info();
int func_about_diag4();
int func_trouble_shoot();
int func_bulletin_board();
int func_marketing_info();

char revision_level [] = "v4.1";

struct menu_struc menu_main [] =
{
    { '?',*func_help,  4, 'C', "Main Menu",MENU_OFF },
    { '1',*show_system_info,      7,  'L', " 1. SYSTEM INFORMATION" },
/*    { '2',*func_ibmint,           8,  'L', " 2. TEST PC INTERFACE CARD" },*/
    { '2',*show_pin_driver_info,  8,  'L', " 2. TEST ALLPRO" },
    { '3',*func_config,           9,  'L', " 3. DIAGNOSTIC CONFIGURATION " },
    { '.',*func_help, 13, 'L', "----------------------------------------------------------------------------"},
    { '4',*func_about_diag4,     16, 'L', " 4. ABOUT DIAG4"},
    { '5',*func_bulletin_board,  17, 'L', " 5. BULLETIN BOARD"},
    { '6',*func_trouble_shoot,   18, 'L', " 6. TROUBLE SHOOTING"},
    { '7',*func_marketing_info,  19, 'L', " 7. MARKETING INFO"},
/*    { '4',*func_analog_cont,     12,  'L', " 4. TEST ANALOG CONTROL" },*/
/*    { '5',*show_pin_driver_info, 13,  'L', " 5. TEST PIN DRIVERS" },*/
/*    { '6',*func_trblsht,         14,  'L', " 6. TROUBLE SHOOT",MENU_OFF },*/
/*    { '8',*func_se6440,          16,  'L', " 8. TEST SE6440",MENU_OFF },*/
    { '\0',*func_null, 0,  0, "" }
};



struct menu_struc menu_help [] =
{
    { '0',*func_null,  4, 'C', "ALLPRO DIAGNOSTIC HELP MENU" },
    { '0',*func_null,  6, 'C', "No help at this time" },
    { '\0',*func_null, 0,  0, "" }
};



struct menu_struc menu_null [] =
{
    { '0',*func_null,  4, 'C', "ALLPRO DIAGNOSTIC" },
    { '0',*func_null,  6, 'C', "This command is not available at this time" },
    { '\0',*func_null, 0,  0, "" }
};



char menu_depth [MAX_DEPTH];
int menu_level;


/*	Subttl Main entrance for allpro diagnostic 2   */

main (argc, argv)
int argc;
char *argv [];
{

    int func_null ();
    int i;

    for ( i = 0; i < MAX_DEPTH ; i++ )
    {
	menu_depth [i] = 0;
    }

    if (!initialize_diagnostic ())
    {
	printf ("No .cfg File Found");
	keybrd_getc ();
    }

    get_video_mode();
    if (vid_mod == 7 || vid_mod == 15)	     /*  monochrome  */
    {
	cursor_top = 12;
	cursor_bottom = 13;
	set_mono_mode ();
    }
    else
    {
	cursor_top = 6;
	cursor_bottom = 7;
    }

    initialize_windows (status_window_table, status_display_table, MAX_WNDS, "ALLPRO - Universal Programmer Diagnostic - %s", revision_level);
    setup_window(WND_USER_INPUT);
    hide_cursor();
    pos_write_window(WND_USER_INPUT,10,20,"Checking System, Please wait!");
    pump ();							/* unlock udi interface for access		*/

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

    init_equip_struc();

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

    menu_level = 0;
    menu_depth [menu_level] = '1';                 /* select main menu */

/*
    if(se6440_flag)
    {
	menu_main[3].flag |= MENU_OFF;
	menu_main[7].flag |= MENU_OFF;
    }
    else if (allpro88_flag)
    {
	menu_main[4].flag |= MENU_OFF;
	menu_main[9].flag |= MENU_OFF;
    }
    else
    {
	menu_main[4].flag |= MENU_OFF;
	menu_main[9].flag |= MENU_OFF;
    }
*/
    select_command ( menu_main );

    reset_allpro();
    unpump ();							/* lock udi interface from access		*/
    video_clear_screen();					/* done 					*/
    crt_pos_cursor (22,25,0);
    show_cursor();
    printf ( "Have a nice day !!!");
    exit (0);
}



/*	Subttl	Select command */
/******************************************************************************/
/* Select command prints a menu on the screen, controls cursor movement and   */
/* allows the operator to select an item from the menu. When an item is       */
/* selected, the function pointer for that selection is called. 	      */
/*									      */
/* Enter:   menu_struc_ptr	= pointer to structure containing menu info.  */
/*									      */
/* Call:    select_command	(menu_struc_ptr)			      */
/*									      */
/* Return:  selected function						      */
/*									      */
/******************************************************************************/

select_command ( menu_struc_ptr )
struct menu_struc menu_struc_ptr [];
{
    int keychar;
    char command;
    int i;
    int remain;
    int cur_row;
    int cur_col;
    int cmnd;
    int highlight_size;

    highlight_width = get_menu_message_size(menu_struc_ptr);
    print_menu ( menu_struc_ptr );
    cmnd = menu_pos_cursor ( menu_struc_ptr );	  /* get position of first command */
    if(cmnd == 0)
    {
	keybrd_getc();
	return;
    }
    for ( remain = TRUE; remain == TRUE; )
    {
	highlight_size = highlight_width;
	if ( cmnd )
	{
	    highlight_menu_option(menu_struc_ptr,cmnd,REVERSE_VIDEO);
	}

	switch (keychar = keybrd_getc ())
	{
	    case KEY_ESC:
	    {
		remain = FALSE;
		break;
	    }
	    case KEY_F9:
	    {
		if(se6440_flag) select_zif_socket();
		print_menu ( menu_struc_ptr );
		break;
	    }
	    case KEY_CURSOR_UP:
	    {
		highlight_menu_option(menu_struc_ptr,cmnd,NORMAL_VIDEO);
		for(i=cmnd-1;menu_struc_ptr [i].match_char != '?';i--)
		{
		    if(!(menu_struc_ptr[i].flag & MENU_OFF) && isdigit(menu_struc_ptr[i].match_char))
		    {
			cmnd = i;
			break;
		    }
		}
/*
		if ( menu_struc_ptr [cmnd].match_char > '1' && menu_struc_ptr [cmnd].match_char <= '9')
		{
		    highlight_menu_option(menu_struc_ptr,cmnd,NORMAL_VIDEO);
		    cmnd--;
		}
*/
		break;
	    }
	    case KEY_CURSOR_DOWN:
	    {
		highlight_menu_option(menu_struc_ptr,cmnd,NORMAL_VIDEO);
		for(i=cmnd+1;menu_struc_ptr [i].match_char != '\0';i++)
		{
		    if(!(menu_struc_ptr[i].flag & MENU_OFF) && isdigit(menu_struc_ptr[i].match_char))
		    {
			cmnd = i;
			break;
		    }
		}
/*
		if ( menu_struc_ptr [cmnd + 1].match_char != '\0' )
		{
		    highlight_menu_option(menu_struc_ptr,cmnd,NORMAL_VIDEO);
		    cmnd++;
		}
*/
		break;
	    }
	    case KEY_CR:
	    {
		keychar = menu_struc_ptr [cmnd].match_char;
	    }
	    case '1':
	    case '2':
	    case '3':
	    case '4':
	    case '5':
	    case '6':
	    case '7':
	    case '8':
	    case '9':
	    {
		for ( i = 0; ((menu_struc_ptr[i].match_char != keychar)
		|| (menu_struc_ptr [i].flag & MENU_OFF))
		&& (menu_struc_ptr [i].match_char != '\0'); i++ );
		if ( menu_struc_ptr [i].match_char )
		{
		    highlight_menu_option(menu_struc_ptr,cmnd,NORMAL_VIDEO);
		    cmnd = i;
		    menu_depth [++menu_level] = menu_struc_ptr [i].match_char;
		    (*menu_struc_ptr[i].func)();
		    menu_depth [menu_level--] = 0;
		    print_menu ( menu_struc_ptr );
		}
		break;
	    }
	}
	highlight_width = highlight_size;
    }
}



func_help ()
{
    select_command ( menu_help );
}





int func_null ()
{
    select_command ( menu_null );
}






/*	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;
    }
    get_system_info();
}



/*	Subttl	Print menu ( from data in menu_ptr )  */
print_menu ( menu_ptr )
struct menu_struc menu_ptr[];
{
    int i;

    setup_window(WND_FUNC_SELECT);
    write_window_border(WND_FUNC_SELECT,'C', menu_ptr [0].message );
    for ( i = 1; menu_ptr[i].match_char != '\0'; i++ )
    {
	if(menu_ptr[i].flag & MENU_OFF)
	{
	    status_window_table[0].window_attr &= 0xf7;
	    status_window_table[1].window_attr &= 0xf7;
	    status_window_table[2].window_attr &= 0xf7;
	    write_window (WND_FUNC_SELECT,menu_ptr[i].set_menu_row,menu_ptr[i].set_menu_col,menu_ptr[i].message);
	    status_window_table[0].window_attr |= 0x08;
	    status_window_table[1].window_attr |= 0x08;
	    status_window_table[2].window_attr |= 0x08;
	}
	else
	{
	    write_window (WND_FUNC_SELECT,menu_ptr[i].set_menu_row,menu_ptr[i].set_menu_col,menu_ptr[i].message);
	}
    }
}

menu_pos_cursor ( menu_ptr )
struct menu_struc menu_ptr [];
{
    int i;

    for ( i = 0; menu_ptr [i].match_char != '\0'; i++ )
    {
	if (isdigit(menu_ptr[i].match_char) && !(menu_ptr [i].flag & MENU_OFF))
	{
	    return ( i );
	}
    }
    return ( 0 );
}

get_menu_message_size ( menu_ptr )
struct menu_struc menu_ptr [];
{
    int i;
    int size, strsz;
    size = 0;
    for ( i = 0; menu_ptr [i].match_char != '\0'; i++ )
    {
	if(menu_ptr[i].match_char != '?' && menu_ptr[i].match_char != '.' )
	{
	    strsz = strlen(menu_ptr[i].message);
	    if ( strsz > size) size = strsz;
	}
    }
    return (size);
}






/*	Subttl	Initialize All-Pro*/
reset_allpro ()
{
    int pin, pins;						      /* pin counter to reset pins		      */

    pump();
    if(se6440_flag) udi_write_mem(0x298,0xff);	 /*  enable all sockets se6440 */
    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);

    pins = max_pins;

    for (pin = 1; pin <= pins; pin++)
    {
	set_pin_cnf (pin, PD_DRIVER_ON);
	set_pin_dac (pin, 0);
    }
    /* clear all registers on zif module */
    if(!se6440_flag)
    {
	for(pin = 0x280;pin < 0x290;pin++)
	{
	    udi_write_mem(pin,0);
	}
    }
}

highlight_menu_option(menu_ptr,offset,attr)
struct menu_struc menu_ptr[];
int offset, attr;
{
    int col;
    switch(menu_ptr[offset].set_menu_col)
    {
	case 'L': col = 1; break;
	case 'R':
	    col = dis_table[WND_FUNC_SELECT].act_y_lower;
	    col = col - strlen(menu_ptr[offset].message);
	    break;
	case 'C':
	    col =  dis_table[WND_FUNC_SELECT].act_y_lower;
	    col -= dis_table[WND_FUNC_SELECT].act_y_upper;
	    col -= strlen(menu_ptr[offset].message);
	    col /= 2;
	    col += dis_table[WND_FUNC_SELECT].act_y_upper;
	    break;
    }
    highlight_window_line(WND_FUNC_SELECT,
	menu_ptr[offset].set_menu_row,
	col,
	highlight_width,attr);
}


highlight_window_line(display,line,scol,length,attr)
int display, line, scol,length,attr;
{
    int window;
    int x, y1, y2, dtype;

    window = dis_table [display].display_window;
    x = win_table [window].win_x_upper + line - 1;
    y1 = win_table [window].win_y_upper + scol - 1;
    y2 = y1 + length;
    dtype = get_window_attr (display, attr);
    highlight(x,y1,y2,dtype);
}

/*  This routine reads chars from the screen and write them back with	    */
/*  specified attribute.						    */
highlight (row, col1, col2, attr)
int row, col1, col2, attr;
{
    int i;

    for (i = col1; i <= col2; i++)
    {
#asm
	Push	BP
	Mov	DH, [bp + 4]
	Mov	DL, [bp - 2]
	Mov	BH, 0
	Mov	AH, 2	    ;set cursor position
	Int	010H

	Mov	AH, 08h     ;read char
	Xor	BX, BX
	Int	10h

	Mov	BL, [bp + 10]	;write the same char
	Mov	AH, 9		;with specified attribute
	Mov	CX, 1
	Int	10h
	Pop	BP
#endasm
    }
}


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);
}

set_mono_mode ()
{
    int i;

    for (i = 0; i < CWD_MAX; i++)
    {
	status_window_table [i].window_attr = 0x07;
	status_window_table [i].border_attr = 0x07;
    }
}

/* Status Windows */
struct window_def_struc status_window_table [MAX_WNDS] =
{
    {
	-1,
	2, 2, 24, 43,
	0, 0, 0,
	0x1e, 0x1f
    },
    {
	-1,
	2, 44, 24, 79,
	0, 0, 0,
	0x1e, 0x1f
    },
    {
	-1,
	2, 2, 24, 79,
	0, 0, 0,
	0x1e, 0x1f
    },
    {
	-1,
	2, 2, 15, 79,
	0, 0, 0,
	0x1e, 0x1f
    }
};

struct window_usage_struc status_display_table [MAX_WND_TYPES] =
{
    {
	CWD_ZIFS,
	1, 1, 12, 76,
	0,
	"Zif Sockets"
    },
    {
	CWD_AUX,
	1, 1, 12, 76,
	0,
	"Session Status"
    },
    {
	CWD_ZIFS,
	1, 1, 12, 76,
	0,
	"Log/Unlog Sockets"
    },
    {
	CWD_TOP,
	1, 1, 12, 76,
	0,
	"Diagnostic Information"
    },
    {
	CWD_ALL,
	1, 1, 22, 76,
	0,
	"ALLPRO - Diagnostic Main Menu"
    },
    {
	CWD_ALL,
	1, 1, 22, 76,
	0,
	"ALLPRO - Analog Test and Calibrate"
    },
    {
	CWD_AUX,
	1, 1, 12, 76,
	0,
	"Messages"
    },
    {
	CWD_ZIFS,
	1, 1, 12, 76,
	0,
	"Test Results"
    },
    {
	CWD_AUX,
	1, 1, 12, 76,
	0,
	"Messages/Inputs"
    },
    {
	CWD_ALL,
	1, 1, 22, 76,
	0,
	"Statistics"
    },
    {
	CWD_ALL,
	1, 1, 22, 76,
	0,
	"System Status"
    },
    {
	CWD_ALL,
	1, 1, 22, 76,
	0,
	"Pindriver Selection"
    },
};


static int ctop, cbot;
static int cur_cnt = 0;

hide_cursor ()
{
    int temp;
    if(!cur_cnt)
    {
	temp = crt_get_cur_pos(0);
	ctop = temp >> 8;
	cbot = temp & 0xff;
	crt_cursor_type (32, 32);
    }
    cur_cnt++;
}

show_cursor ()
{
    if(--cur_cnt == 0)
	crt_cursor_type (ctop, cbot);
}

/*	This file will be used to display the ldi message file. This file
	file should be in the directory where all the base files
	are located. The maximum number of lines in the file must not
	exceed 500. */

/*	Subttl	Equates*/
char *strings [500];

func_about_diag4()
{
    display_messages("DIAG.MSG");
}
func_bulletin_board()
{
    display_messages("BBS.MSG");
}
func_trouble_shoot()
{
    display_messages("TROUBLE.MSG");
}
func_marketing_info()
{
    display_messages("MARKET.MSG");
}

display_messages(fn)
char *fn;
{
    int status;

    FILE *fptr;
    FILE *fopen ();
    unsigned int ctr;
    unsigned int file_line_ptr;
    unsigned int exit_flag;
    unsigned int key;
    unsigned int total_lines;
    unsigned int wnd_lines;  /* total lines available in the window */
    char buffer [85];

    char *malloc ();

    clear_window (WND_FUNC_SELECT);
    write_window_border(WND_FUNC_SELECT,'C',"");
    setup_window (WND_DIAG_INFO);
    clear_window(WND_DIAG_INFO);
    if ((fptr = fopen (fn, "r")) == 0)
    {
	clear_window (WND_DIAG_INFO);
	write_window (WND_DIAG_INFO, 6, 'C', fn);
	write_window (WND_DIAG_INFO, 7, 'C', "Message File Cannot Be Opened.");
	write_window (WND_DIAG_INFO, 8, 'C', "Press any key to continue.");
	while (keyboard_status () == -1){}
    }
    else
    {
	file_line_ptr = 0;
	setup_window (WND_DIAG_INFO);
	wnd_lines = 12;

	write_window (WND_FUNC_SELECT, 16, 'C', "Use the PgUp and PgDn keys");
	write_window (WND_FUNC_SELECT, 17, 'C', "to view the messages.");
	write_window (WND_FUNC_SELECT, 18, 'C', "Press Esc to return to Main Menu");

	/* calculate number of lines */
	for (total_lines = 0; fgets (buffer, 85, fptr) != 0; total_lines++){}

	/* reset file pointer */
	fseek (fptr, 0L, 0);

	exit_flag = FALSE;
	for (ctr = 0; exit_flag == FALSE; ctr++)
	{
	    if (fgets (buffer, 85, fptr) == 0)
	    {
		exit_flag = TRUE;
	    }
	    else
	    {
		terminate_with_null (buffer);
		strings [ctr] = malloc (strlen (buffer) + 1);
		strcpy (strings [ctr], buffer);
	    }
	}

	fclose (fptr);

	exit_flag = FALSE;
	while (exit_flag == FALSE)
	{
	    clear_window (WND_DIAG_INFO);
	    for (ctr = 0; (ctr < wnd_lines) && ((file_line_ptr + ctr) < total_lines); ctr++)
	    {
		write_window (WND_DIAG_INFO, ctr+1, 'L', strings [file_line_ptr+ctr]);
	    }

	    key = keybrd_getc ();

	    switch (key)
	    {
		case KEY_ESC:
		{
		    exit_flag = TRUE;
		    break;
		}
		case KEY_PAGE_DOWN:
		{
		    if ((file_line_ptr + wnd_lines) < total_lines)
		    {
			file_line_ptr += wnd_lines;
		    }
		    break;
		}
		case KEY_PAGE_UP:
		{
		    if ((int)(file_line_ptr - wnd_lines) >= 0)
		    {
			file_line_ptr -= wnd_lines;
		    }
		    break;
		}
	    }
	}
	for (ctr = 0; ctr < total_lines; ctr++)
	{
	    free (strings [ctr]);
	}
    }
    return (TRUE);

}



/*  This routine takes in_buffer and looks for line feed char and replaces  */
/*  with a NULL.							    */
terminate_with_null (str)
char *str;
{
    int i;

    for (i=0; str [i] != '\12' && str [i] != ';' && i < 200; i++);
    str [i] = '\0';
}
