/*	Title	All-Pro Diagnostics*/
/******************************************************************************/
/*				     Diaghdwr				      */
/*			       All-pro Diagnostic Pin driver tests	      */
/*									      */
/* Module ...................... DIAGHDWR				      */
/* Title ....................... All-pro Diagnostic Pin driver tests	      */
/* Developing Engineer ......... Steven T. Harr 			      */
/* Company ..................... Logical Devices			      */
/* Revision Level .............. 1.00					      */
/* Date of Last Revision ....... 08-13-90				      */
/* Last Revision by ............ STH					      */
/*									      */
/*									      */
/******************************************************************************/
/*	Subttl	Includes*/
#include <stdio.h>
#include <ctype.h>
#include "pindrivr.h"
#include "diag2.h"
#include "windows.h"
#include "window.h"
#include "keybrd.h"

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

#define  MODULE_ADDR	      0x280
#define  MODULE_ADDR0	      0x280
#define  MODULE_ADDR1	      0x281
#define  MODULE_ADDR2	      0x282

static int l_pin = 1;
static unsigned int error[90];
static unsigned int error_acc[90];
unsigned int decouple_register [3];

unsigned char decouple_table [8] [2] =
{
    {34, 0x01},
    {32, 0x02},
    {30, 0x04},
    {29, 0x08},
    {28, 0x10},
    {27, 0x20},
    {20, 0x40},
    {40, 0x80}
};

unsigned char decouple_table_2 [16] [2] =
{
    {40, 0x01},
    {28, 0x02},
    {29, 0x04},
    {30, 0x08},
    {31, 0x10},
    {32, 0x20},
    {34, 0x40},
    {39, 0x80},
    {14, 0x01},
    {11, 0x02},
    { 9, 0x04},
    {27, 0x08},
    {21, 0x10},
    {20, 0x20},
    { 7, 0x40},
    { 1, 0x80}
};

extern unsigned int phys_pin_offset;
extern unsigned int pin_base_address[];
extern int real_pin [];
extern unsigned int max_pins;
extern unsigned char analog_id;

int pullup_test(pin)
int pin;
{
    int status = TRUE;
    udi_write_dac(PU_CONTROL_DAC,1000);
    udi_write_dac(THRESH_HOLD_DAC,900);
    set_pin_cnf(pin,PU_DRIVER_ON);
    delay_us(50);
    if (!read_pin(pin)) status = FALSE;
    udi_write_dac(THRESH_HOLD_DAC,1100);
    if (read_pin(pin)) status = FALSE;
    udi_write_dac(THRESH_HOLD_DAC,200);
    set_pin_cnf(pin,GD_DRIVER_ON);
    if (read_pin(pin)) status = FALSE;
    return status;
}

int pulldown_test(pin)
int pin;
{
    int status = TRUE;
    set_pin_dac(pin,2200);
    set_pin_cnf(pin,SRC_DRIVER_ON);
    udi_write_dac(THRESH_HOLD_DAC,2000);
    delay_us(50);
    if (!read_pin(pin)) status = FALSE;
    udi_write_dac(THRESH_HOLD_DAC,50);
    set_pin_cnf(pin,0);
    if (system_info.analog_id == 3 && !read_pin(pin)) status = FALSE;
    set_pin_cnf(pin,PD_DRIVER_ON);
    delay_us(20);
    if (read_pin(pin)) status = FALSE;
    set_pin_cnf(pin,GD_DRIVER_ON);
    return status;
}

int source_test(pin)
int pin;
{
    int status = TRUE;
    udi_write_dac(THRESH_HOLD_DAC,2140);
    set_pin_dac(pin,2200);
    delay_us(50);
    if (read_pin(pin)) status = FALSE;
    set_pin_cnf(pin,SRC_DRIVER_ON);
    if (!read_pin(pin)) status = FALSE;
    udi_write_dac(THRESH_HOLD_DAC,2270);
    if (read_pin(pin)) status = FALSE;
    udi_write_dac(THRESH_HOLD_DAC,200);
    set_pin_cnf(pin,GD_DRIVER_ON);
    if (read_pin(pin)) status = FALSE;
    set_pin_dac(pin,0);
    return status;
}

int ground_test(pin)
int pin;
{
    int status = TRUE;
    udi_write_dac(THRESH_HOLD_DAC,50);
    set_pin_cnf(pin,PU_DRIVER_ON | GD_DRIVER_ON);
    delay_us(50);
    if (read_pin(pin)) status = FALSE;
    udi_write_dac(THRESH_HOLD_DAC,200);
    return status;
}

int clk_test(pin)
int pin;
{
    int status = TRUE;
    if(system_info.analog_id == 3)
    {
	udi_write_mem(PCLOCK,0x01);
	udi_write_dac(THRESH_HOLD_DAC,70);
	set_pin_cnf(pin, CLK0_DRIVER_ON);
	if (read_pin(pin)) status = FALSE;
	udi_write_dac(THRESH_HOLD_DAC,250);
	udi_write_mem(PCLOCK,0x81);
	if (!read_pin(pin)) status = FALSE;
	udi_write_dac(THRESH_HOLD_DAC,70);
	set_pin_cnf(pin, CLK1_DRIVER_ON);
	if (read_pin(pin)) status = FALSE;
	udi_write_dac(THRESH_HOLD_DAC,250);
	udi_write_mem(PCLOCK,0x01);
	if (!read_pin(pin)) status = FALSE;
	set_pin_cnf (pin,GD_DRIVER_ON);
	udi_write_mem(PCLOCK,0x00);
    }
    else if (system_info.analog_id != 2) status = FALSE;
    return status;
}

int current_test(pin)
int pin;
{
    int status = TRUE;
    if(system_info.analog_id == 3)
    {
	udi_write_mem(VIPI_DAC,0);
	udi_write_mem(VIPV_DAC,100);
	set_pin_cnf(pin, TTL_LOW_DRIVER_ON | CUR_DRIVER_ON);
	udi_write_mem(VIPI_DAC,80 / 2 + 10);
	udi_write_dac(THRESH_HOLD_DAC,300);
	if (read_pin(pin)) status = FALSE;
	udi_write_dac(THRESH_HOLD_DAC,150);
	if (!read_pin(pin)) status = FALSE;
	udi_write_mem(VIPV_DAC,0);
	udi_write_mem(VIPI_DAC,0);
	set_pin_cnf(pin, GD_DRIVER_ON);
    }
    else if (system_info.analog_id != 2) status = FALSE;
    return status;
}
int ttl_hi_test(pin)
int pin;
{
    int status = TRUE;
    udi_write_dac(THRESH_HOLD_DAC,270);
    set_pin_cnf(pin,TTL_HI_DRIVER_ON | TTL_LOW_DRIVER_ON);
    delay_us(50);
    if (!read_pin(pin)) status = FALSE;
    udi_write_dac(THRESH_HOLD_DAC,500);
    if (read_pin(pin)) status = FALSE;
    udi_write_dac(THRESH_HOLD_DAC,200);
    set_pin_cnf(pin,GD_DRIVER_ON);
    return status;
}
int ttl_low_test(pin)
int pin;
{
    int status = TRUE;
    if(system_info.analog_id == 3)
    {
	udi_write_dac(THRESH_HOLD_DAC,70);
	set_pin_cnf(pin,PU_DRIVER_ON | TTL_LOW_DRIVER_ON);
	delay_us(50);
	if (read_pin(pin)) status = FALSE;
	udi_write_dac(THRESH_HOLD_DAC,200);
	set_pin_cnf(pin,GD_DRIVER_ON);
    }
    else if (system_info.analog_id != 2) status = FALSE;
    return status;

}

int sticky_test(pin)
int pin;
{
    int status = TRUE;
    int i;

    udi_write_dac(THRESH_HOLD_DAC,200);
    udi_write_dac(PU_CONTROL_DAC,500);
    set_pin_cnf(pin,PU_DRIVER_ON);
    if (!read_pin(pin)) status = FALSE;

    for (i=1;i<=88;i++)
    {
	if(real_pin[i] && i != pin)
	{
	    if (read_pin(i)) status = FALSE;
	}
    }
    set_pin_cnf(pin,GD_DRIVER_ON);
    return status;

}

int decouple_test(pin)
int pin;
{
    int status = TRUE;
    udi_write_dac(THRESH_HOLD_DAC,300);
    set_cap_at_pin(pin, ON);
    set_pin_cnf(pin, GD_DRIVER_ON);
    if(read_pin(pin)) status = FALSE;
    set_pin_dac (pin, 0);
    set_pin_cnf(pin, SRC_DRIVER_ON);
    set_pin_dac (pin, 1000);
    udi_write_dac(THRESH_HOLD_DAC,1100);
    if (read_pin(pin)) status = FALSE;
    udi_write_dac(THRESH_HOLD_DAC,900);
    if (!read_pin(pin)) status = FALSE;
    udi_write_dac(THRESH_HOLD_DAC,300);
#asm
    cli
#endasm
    set_pin_cnf(pin, PD_DRIVER_ON);
    delay_us(100);
    if(!read_pin(pin)) status = FALSE;
#asm
    sti
#endasm
    if (!set_cap_at_pin(pin, OFF)) status = TRUE;
    set_pin_cnf(pin, GD_DRIVER_ON);
    set_pin_dac (pin, 0);
    delay_us(50);
    return status;
}


int (*func[])() =
{
    *source_test,
    *pulldown_test,
    *pullup_test,
    *ground_test,
    *ttl_hi_test,
    *ttl_low_test,
    *current_test,
    *clk_test,
    *decouple_test,
    *sticky_test
};



pindriver_tests (error)
unsigned int error [];
{
    int i, pin, status;

    reset_allpro();
    setup_supplies(2400,200,600,30);
    delay_ms(200);
    status = 0;
    for(pin=1;pin <= max_pins;pin++)
    {
	set_pin_cnf(pin,GD_DRIVER_ON);
    }

    for(pin=1;pin <= max_pins;pin++)
    {
	get_analog_id();
	system_info.analog_id = analog_id;
	system_info.module_id = udi_read_mem(0x280);
	error[pin] = 0;
	if(real_pin[pin])
	{
	    for (i=0;i<sizeof(func)/sizeof(func[0]);i++)
	    {
		error[pin] |= ((*func[i])(pin)) << i;
	    }
	}
	status |= error[pin];
	error_acc[pin] &= error[pin];
    }
    reset_allpro();
    return !status;
}

char err_ch [] = {"SDUGHLICPB"};

show_pin_driver_info()
{
    int i, pn;
    int ch;
    int stop = FALSE;

    for(pn=1;pn <= max_pins;pn++)
    {
	error_acc[pn] = 0xffff;
    }
    setup_window (WND_TEST_STATISTICS);
    clear_window(WND_TEST_STATISTICS);
    write_window_border(WND_TEST_STATISTICS,'C',"S=Src D=pullDn U=pullUp G=Gnd H=High L=Low I=current C=Clk P=caP B=Bit");

    while(!stop)
    {
	pindriver_tests(error);
	{
	    for(pn=1;!stop && pn<=max_pins;pn++)
	    {
		if(key_queue_check() != -1)
		{
		    ch = keybrd_getc();
		    if(ch == KEY_F10)
		    {
			loop_on_pin();
		    }
		    else if(ch == KEY_F9)
		    {
			write_window(WND_TEST_STATISTICS,1,'C',"Test history");
			for(pn=1;pn<=max_pins;pn++)
			{
			    show_pin_test(pn,error_acc);
			}
			keybrd_getc();
			clear_window_line(WND_TEST_STATISTICS,1);
			break;
		    }
		    else stop = TRUE;
		}
		show_pin_num(pn);
		show_pin_test(pn,error);
	    }
	}
    }
}


loop_on_pin()
{
    int i, pin, ch;

    reset_allpro();
    setup_supplies(2400,200,600,30);
    delay_ms(200);
    for(pin=1;pin <= max_pins;pin++)
    {
	set_pin_cnf(pin,GD_DRIVER_ON);
    }
    highlight_window_line(WND_TEST_STATISTICS,
	(l_pin-1)%20+2,(l_pin-1)/20*15+2,2,REVERSE_VIDEO);
    while(1)
    {
	system_info.analog_id = analog_id;
	system_info.module_id = udi_read_mem(0x280);
	if(key_queue_check() != -1)
	{
	    ch = keybrd_getc();
	    highlight_window_line(WND_TEST_STATISTICS,
		(l_pin-1)%20+2,(l_pin-1)/20*15+2,2,NORMAL_VIDEO);
	    switch(ch)
	    {
		case KEY_CURSOR_UP:
		    if(l_pin > 1) l_pin--;
		break;
		case KEY_CURSOR_DOWN:
		    if(l_pin < max_pins) l_pin++;
		break;
		case KEY_CURSOR_LEFT:
		    if((l_pin - 20) >= 1) l_pin -= 20;
		break;
		case KEY_CURSOR_RIGHT:
		    if((l_pin + 20) <= max_pins) l_pin += 20;
		break;
		case KEY_ESC:
		    reset_allpro();
		    return();
		break;
	    }
	    highlight_window_line(WND_TEST_STATISTICS,
		(l_pin-1)%20+2,(l_pin-1)/20*15+2,2,REVERSE_VIDEO);
	}
	error[l_pin] = 0;
	if(real_pin[l_pin])
	{
	    for (i=0;i<sizeof(func)/sizeof(func[0]);i++)
	    {
		error[l_pin] |= ((*func[i])(l_pin)) << i;
	    }
	}
	show_pin_test(l_pin,error);
	error_acc[l_pin] &= error[l_pin];
    }
    reset_allpro();
}

show_pin_num(pn)
int pn;
{
    pos_write_window(WND_TEST_STATISTICS, (pn-1)%20+2,(pn-1)/20*15+2,"%2d",pn);
}

show_pin_test(pn,err)
int pn;
unsigned int *err;
{
    int i;
    pos_write_window(WND_TEST_STATISTICS, (pn-1)%20+2,(pn-1)/20*15+5,"");
    if (real_pin[pn])
    {
	for(i=0;i<sizeof(func)/sizeof(func[0]);i++)
	{
	    printf("%c",err[pn]&(1<<i)?'+':err_ch[i]);
	}
    }
}

set_cap_at_pin(pin,state)
int pin, state;
{
    int i;
    switch(system_info.module_id)
    {
	case 0x11:
	if((pin >= 1 && pin <= 40) || (pin >= 61 && pin <= 68))
	{
	    udi_write_mem(0x280 + (pin_base_address[pin+phys_pin_offset] >> 4),state);
	    return(TRUE);
	}
	break;
	case 0x02:
	for (i = 0; i < 8; i++)
	{
	    if (decouple_table_2 [i] [0] == pin)
	    {
		if (state)
		    decouple_register [0] |= decouple_table [i] [1];
		else
		    decouple_register [0] &= ~decouple_table [i] [1];
		udi_write_mem (MODULE_ADDR, decouple_register [0]);
		return(TRUE);
	    }
	    else if (decouple_table_2 [i + 8] [0] == pin)
	    {
		if (state)
		    decouple_register [1] |= decouple_table [i + 8] [1];
		else
		    decouple_register [1] &= ~decouple_table [i + 8] [1];
		udi_write_mem (MODULE_ADDR1, decouple_register [1]);
		return(TRUE);
	    }
	}
	break;
	case 0x01:
	for (i = 0; i < 8; i++)
	{
	    if (decouple_table [i] [0] == pin)
	    {
		if (state)
		    decouple_register [0] |= decouple_table [i] [1];
		else
		    decouple_register [0] &= ~decouple_table [i] [1];
		udi_write_mem (MODULE_ADDR, decouple_register [0]);
		return(TRUE);
	    }
	}
	break;
	default:
	    /* force pin to fail if module is not valid */
	    return TRUE;
	break;
    }
    return FALSE;
}

