/******************************************************************************
 *
 *	EPROM DIAGNOSTIC
 *
 * This module contains the eprom diagnostic tests
 *
 * History:
 *   +----------+------------+------------------------------------------------+
 *   |   Date   |     by     |     Description                                |
 *   +----------+------------+------------------------------------------------+
 *   |          | 	     | Written                                        |
 *   +----------+------------+------------------------------------------------+
 *
 * The macros ROM_BUSWIDTH and ROM_START are used.
 * ROM_BUSWIDTH - is the width of the bus in bytes (one of: 1,2,4,8).
 * ROM_START - is the EPROM's starting address (hexa).
 *
 * When the bus width is larger than 1 byte, the consecutive addresses
 * point to the consecutive EPROMs (address 0x0000 is on the first EPROM,
 * address 0x0001 is on the second EPROM, etc.) .
 *
 **********************************************************************/


#include "cc_def.h"
#include "diag.h"

/* Forward functions */
/*********************/

private boolean test_stuck_on_1(/*rom_number,&sum_result*/);
private boolean test_stuck_on_0(/*rom_number,&sum_result*/);
private unsigned short find_stuck_bit(/*sum_result,stuck_on_what*/);

/****************************************************************************
 *
 *	test_eprom__()
 *
 ****************************************************************************/

public char *test_eprom__()
{
    unsigned short rom_number;
    boolean rom_test_result;
    byte sum_result;

    for (rom_number = 0; rom_number < ROM_BUSWIDTH; rom_number++)
    {
	rom_test_result = test_stuck_on_1(rom_number,&sum_result);
	if (!rom_test_result)
	{
	    strcpy(error,"FAILURE: BIT No.");
	    bin_to_hex__(find_stuck_bit(sum_result,1), &error[strlen(error)], 'D');
	    strcpy(&error[strlen(error)]," STUCK AT 1, IN EPROM ");
	    bin_to_hex__(rom_number, &error[strlen(error)], 'D');
	    return (error);
	}
	rom_test_result = test_stuck_on_0(rom_number,&sum_result);
	if (!rom_test_result)
	{
	    strcpy(error,"FAILURE: BIT No. ");
	    bin_to_hex__(find_stuck_bit(sum_result,0), &error[strlen(error)], 'D');
	    strcpy(&error[strlen(error)]," STUCK AT 0, IN EPROM ");
	    bin_to_hex__(rom_number, &error[strlen(error)], 'D');
	    return (error);
	}
    }
    return NULL;
}

/****************************************************************************
 *
 *	test_stuck_on_1()
 *
 * performs a logical AND operation on all EPROM addresses,
 * expecting to get a '0' result.
 *
 ****************************************************************************/

private boolean test_stuck_on_1(rom_number,sum_result_ptr)
    unsigned short rom_number;
    byte *sum_result_ptr;
{
    byte *addr;

    *sum_result_ptr = 0xff;
    for (addr = (byte *)ROM_START+rom_number;(unsigned) addr < ROM_START+ROM_SIZE; 
     addr += ROM_BUSWIDTH) {
	*sum_result_ptr = (*sum_result_ptr & *addr);
	if (*sum_result_ptr == 0)
	    break;
    }
    return (*sum_result_ptr == 0);
}

/****************************************************************************
 *
 *	test_stuck_on_0()
 *
 * performs a logical OR operation on all EPROM addresses,
 * expecting to get a '~0' result.
 *
 ****************************************************************************/

private boolean test_stuck_on_0(rom_number,sum_result_ptr)
    unsigned short rom_number;
    byte *sum_result_ptr;
{
    byte *addr;

    *sum_result_ptr = 0x00;
    for (addr = (byte *) ROM_START+rom_number;(unsigned) addr < ROM_START+ROM_SIZE;
     addr += ROM_BUSWIDTH)  {
	*sum_result_ptr = (*sum_result_ptr | *addr);
	if   (*sum_result_ptr == 0xff)
	    break;
    }
    return  (*sum_result_ptr == 0xff);
}

/****************************************************************************
 *
 *	find_stuck_bit()
 *
 ****************************************************************************/

private unsigned short find_stuck_bit(sum_result,stuck_on_what)
    byte sum_result;
    unsigned short stuck_on_what;
{
    unsigned short bit;

    switch(stuck_on_what)
    {
      case 0: for (bit = 0; bit < 8; bit++)
	        if (BIT_OFF(bit,sum_result))
	          break;
	      break;
      case 1: for (bit = 0; bit < 8; bit++)
	        if (BIT_ON(bit,sum_result))
	          break;
	      break;
    }
    return (bit);
}
