/******************************************************************************
 *
 *   DIAGNOSTIC DRIVER FILE
 *
 * This module contains     diagnostic tests
 *
 * History:
 *   +----------+------------+------------------------------------------------+
 *   |   Date   |     by     |     Description                                |
 *   +----------+------------+------------------------------------------------+
 *   |          | 	     | Written                                        |
 *   +----------+------------+------------------------------------------------+
 * 
 *****************************************************************************/


#define DIAG_MAIN


struct diag_desc {
    const char    *name;
    char    *(*test_func)();
    char    pu_entry;
};

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

/* forward functions */
/*********************/
extern unsigned get_ram_size__(/*  */);
extern void init_lcd__();
extern void print_lcd__();
extern void start_diag__(),ilongjmp__();

extern int ram_size__;
extern int dram_size__;
extern int sram_size__;
extern unsigned step_5n_flag__;
extern const char led_tab[];

#define  MAX_TEST 15
#ifndef public

/*
 * Dispatch table entry structure
 */
#if (NON_DE_AVAILABLE)
    struct int_desc {
	unsigned	short	mod;
	unsigned	short	offset;
};
#else
    struct int_desc {
	void (* funcp)();
};
#endif

struct statistic{
    int  runs,fails;
} ;


struct shadow { /* shadow registers definition  */
    volatile unsigned char  ecr;
    volatile unsigned short cfr;
    volatile unsigned short vcr;
    volatile unsigned short lcr;
    volatile unsigned short cnd;
};


#define P_BASE 2

#endif


/*
 * Public variables 
 */
public struct int_desc diag_dispatch__[64];
public unsigned cur_divisor__;

#if (ROM_START < 0x10000 && ROM_START >= 0x0)
void * const mod_table__[4]= {0, 0, start_diag__, 0};
#else
void *mod_table__[4];
#endif


public char error[80];
public char msg__[80];
public struct shadow shadow;
public boolean	  verbose_flag;
public boolean	  debug_flag;
#ifdef CACHE
public boolean	  cache_flag;
#endif

/*
 * Private variables 
 */
private boolean    quit_loop_flag;
private struct statistic  statistic_table__[MAX_TEST];
private char line[80];
private	int num_of_test;


#ifndef public
#  pragma interrupt (default_handler__);
#endif

/*
 * Static functions 
 */
private void display_screen(/* */);
private void test_init(/* */);
private void display_statistic(/* */);
private int get_command(/* loop, halt_on_error*/);
private int create_list (/* line*/);
private boolean sio_get_char(/* chp*/);
private void sio_put_char (/* ch*/);
private void read_str(/* line*/);




/* Command interpratation constants. */
/*************************************/
#define	    QUIT		(-1)
#define	    STATISTIC		(-2)
#define	    SYNTAX_ERROR	(-3)
#define	    VERBOSE_TOGLE 	(-4)
#define	    DEBUG_TOGLE 	(-5)
#define	    CACHE_TOGLE 	(-6)

/* Diagnostic port definition */
/******************************/

#ifndef public
#ifndef DIAG_PORT
#define	    DIAG_PORT	0
#endif
#ifndef DIAG_BAUD
#define DIAG_BAUD cur_divisor__
#endif
#endif

/* 
 * Diagnostics message
 */
#define DIAG_MSG "DIAGNOSTIC VERSION "VERSION"."REVISION

#define HIGH_LIGHT_ON_STRING "\033\133\067\155"
#define HIGH_LIGHT_OFF_STRING "\033\133\060\155"
        /* For LIGHT ON/OFF we don't use print_str since it prints NL */
#define HIGH_LIGHT_ON    sio_put_char(0x1B); /* Turn High-Light ON */ \
    			 sio_put_char(0x5B); \
    			 sio_put_char(0x37); \
    			 sio_put_char(0x6D);

#define HIGH_LIGHT_OFF sio_put_char(0x1B); /* Turn High-Light OFF */ \
    			sio_put_char(0x5B); \
    			sio_put_char(0x30); \
    			sio_put_char(0x6D);

#define HOME_CLEAR_STRING "\033\133\110\033\133\112"
#define HOME_CLEAR print_str(HOME_CLEAR_STRING);


/****************************************************************************
 *
 *	diag_interface__()
 *
 ****************************************************************************/

public void diag_interface__()
{
    boolean	loop, halt_on_error;
    int		cmd;
    char	ch;
    int j;

    test_init();
    isetjmp__();
    INIT_LCD;
    while (1) {
	HOME_CLEAR;
	display_screen();
	PRINT_LCD("ENTER COMMAND");
	cmd = get_command (&loop, &halt_on_error);
	switch (cmd) {
	    case QUIT:
		return;
	    case STATISTIC:
		HOME_CLEAR;
		display_statistic();
#define WAIT_FOR_CR  \
         while ( NOT(sio_get_char(&ch) AND (ch == CR || ch == ' ')))

                print_str("Press <CR> to continue ...");
                WAIT_FOR_CR;
		break;
	    case SYNTAX_ERROR:
		print_str("Syntax error - press <CR> to continue ...");
		WAIT_FOR_CR;
		break;
	    case VERBOSE_TOGLE:
		verbose_flag = NOT verbose_flag;
		break;
	    case DEBUG_TOGLE:
		debug_flag = NOT debug_flag;
		if (debug_flag) {
		    print_str("OK,  Debug ON");
		}
		else {
		    print_str("OK,  Debug OFF");
		}
		break;
#ifdef CACHE
	    case CACHE_TOGLE:
		cache_flag = NOT cache_flag;
		if (cache_flag) {
		    cache_enable__();
		    print_str("OK,  Cache ON");
		}
		else {
		    cache_disable__();
		    print_str("OK,  Cache OFF");
		}
		break;
#endif
	    case  0:
		break;
	    default:
		test_dispatch__(cmd, loop, halt_on_error);
		print_str("Press <CR> to continue ...");
		WAIT_FOR_CR;
		break;
	}
    }
}


/****************************************************************************
 *
 *	test_init()
 *
 ****************************************************************************/


private void test_init()
{
    int	    i;

    DIVISOR(DIAG_BAUD, DIAG_PORT);

    for (i = 0; i < MAX_TEST; i ++) {
	statistic_table__[i].runs = 0;
	statistic_table__[i].fails = 0;
    }
#if (ROM_START < 0x10000 && ROM_START >= 0x0)
    /* Mod table is initialized in ROM */
#else
    mod_table__[P_BASE] = start_diag__;
#endif
    init_uart(DIAG_PORT, DIAG_BAUD, 0);
    for (i = 16; i < 64; i ++) {
#if (NON_DE_AVAILABLE)
	diag_dispatch__[i].mod = (short) mod_table__;
	diag_dispatch__[i].offset = (short) 
                           ((int)default_handler__ - (int)mod_table__[P_BASE]);
#else
	diag_dispatch__[i].funcp = default_handler__;
#endif
    }
    
    /*
     * Initialize NMI and DBG entrys in dispatch table to ilongjmp__
     */
#if (NON_DE_AVAILABLE) 
    diag_dispatch__[1].mod = diag_dispatch__[14].mod = (short) mod_table__ ;
    diag_dispatch__[1].offset = diag_dispatch__[14].offset = (short) 
                                 ((int) ilongjmp__ - (int)mod_table__[P_BASE]);
#else
    diag_dispatch__[1].funcp = ilongjmp__;
#endif

    ram_size__ = 0;
    dram_size__ = 0;
    sram_size__ = 0;
    debug_flag = FALSE;
    verbose_flag = FALSE;
    step_5n_flag__ = 1;
#ifdef INIT_SHADOW
    INIT_SHADOW
#endif
}

/**************************************************************************
 *
 * pu_diag()
 *
 *************************************************************************/

#ifndef DEBUG
#ifdef  CMON

#define DIAG_PU_MSG "POWER UP DIAGNOSTIC VERSION "VERSION"."REVISION
#define PU_PATTERN	0x96a5d30f

extern volatile int pu_pattern__;

extern void pu_diag__()
{
    int i, pu_failed = 0;
    char *response;


    pu_pattern__ = PU_PATTERN;

    for (i = 0; i < 16; i ++) {
#if (NON_DE_AVAILABLE)
        diag_dispatch__[i].mod = (short) mod_table__;
        diag_dispatch__[i].offset = (short) 
                           ((int)default_handler__ - (int)mod_table__[P_BASE]);
#else
        diag_dispatch__[i].funcp = default_handler__;
#endif
    }

    test_init();
    DIAG_BAUD = UART_DIVISOR;
    init_uart(DIAG_PORT, UART_DIVISOR, 0);
    LED(LED_P);			/* display PU messeges */
    HOME_CLEAR;
    print_str(DIAG_PU_MSG);
    DELAY(100000);			/* before initializing the LCD */
    INIT_LCD;
    PRINT_LCD("POWER UP DIAG");
    DELAY(120000);


    step_5n_flag__ = 0x20;	/* dram_5N will run in jumps of 10 	*/
				/* instead of consecutive steps.	*/

    for (i = 0; i < 10; i++) {	/* main dispatch loop */
        if (diag_test_list__[i].pu_entry == TRUE) {
    	LED(led_tab[i]);
    	PRINT_LCD(diag_test_list__[i].name);


    	response = (* diag_test_list__[i].test_func)();	/* run test */
    	if (response != NULL) {		/* on failure */
    	    LED(LED_F);
    	    strcpy(line, diag_test_list__[i].name);
    	    strcat(line, " FAIL");
    	    PRINT_LCD(line);
    	    strcpy(line, diag_test_list__[i].name);
    	    strcat(line, " ");
    	    strcat(line, response);
    	    print_str(line);
    	    pu_failed = TRUE;
    	}
    	else {				/* on success */
    	    LED(LED_P);
    	    strcpy(line, diag_test_list__[i].name);
    	    strcat(line, " PASS");
    	    PRINT_LCD(line);
    	    strcpy(line, diag_test_list__[i].name);
    	    strcat(line, " PASSED");
    	    print_str(line);
    	}
    	DELAY(120000);
        } /* if pu_entry = TRUE */
    } /* for main loop */
/*    strcpy(line, " TOTAL CHECKED RAM SIZE IS: 0x");
    bin_to_hex__(dram_size__ + sram_size__,  &line[strlen(line)],  'D');
    print_str(line); */
    strcpy(line, " DRAM SIZE IS: 0x");
    bin_to_hex__(dram_size__,  &line[strlen(line)],  'D');
    print_str(line);
#ifdef	SRAM_START
    strcpy(line, " SRAM SIZE IS: 0x");
    bin_to_hex__(sram_size__,  &line[strlen(line)],  'D');
    print_str(line);
#endif
#ifdef  DIP_SWITCH
    strcpy(line, "DIP SWITCH: 0x");
    bin_to_hex__(DIP_SWITCH, &line[strlen(line)], 'B');
    print_str(line);
#endif
    if (pu_failed) {
        LED(LED_F);
        PRINT_LCD("POWER UP FAILED");
        strcpy(line, "POWER UP DIAGNOSTICS FAILED");
        print_str(line);
    }
    else {
        LED(LED_P);
        PRINT_LCD("POWER UP PASSED");
        strcpy(line, "POWER UP DIAGNOSTICS PASSED.");
        DELAY(120000);
        PRINT_LCD(MON_NAME" "VERSION"."REVISION);
        print_str(line);
    }
    step_5n_flag__ = 0x1;
}

#endif		/* CMON  */
#endif		/* DEBUG */

/****************************************************************************
 *
 *	default_handler__()
 *
 ****************************************************************************/

public void default_handler__ ()
{
    print_str ("ERROR: UNKNOWN INTERRUPT");
}

const char digit[] = {'0','1','2','3','4','5','6','7','8','9'};

/****************************************************************************
 *
 *	display_screen()
 *
 ****************************************************************************/

private void display_screen()
{
    int	    i;
    char    dec_str[5];

    strcpy(line, "            ");
    strcat(line, MON_NAME);
    strcat(line, "    ");
    strcat(line, DIAG_MSG);
    strcat(line, "            ");
    HIGH_LIGHT_ON;
    print_str(line);
    HIGH_LIGHT_OFF;
    /* print_str(""); */
    for (i = 0; diag_test_list__[i].name != NULL AND i < MAX_TEST; i++) {
	line[0] = '[';
	if (i < 10) {
	    bin_to_dec(i, &dec_str[0]);
	    line[1] = ' ';
	    line[2] = dec_str[0];
	}
	else {
	    bin_to_dec(i, &dec_str[0]);
	    line[1] = dec_str[0];
	    line[2] = dec_str[1];
	}
	line[3] = ']';
	line[4] = '\t';
	strcpy(&line[5], diag_test_list__[i].name);
	print_str(line);
    }
    num_of_test = i;
    print_str("[ s] 	 Display diagnostic results & board setup");
    if (verbose_flag) {
        print_str("[ v]	 Verbose mode ON");
    }
    else {
        print_str("[ v]	 Verbose mode OFF");
    }
    print_str("[ a]	 Run all tests");
    print_str("[ l]	 Loop - repeat <test_list>  stop if failure detected");
    print_str("[ L]	 Loop - repeat all tests stop if failure detected");
    print_str("[ e]	 Eternal loop - repeat <test_list>  forever");
    print_str("[ E]	 Eternal loop - repeat all tests forever");
    print_str("Enter test selection -	[<char>] <test_list>... ");

}

/****************************************************************************
 *
 *	display_statistic()
 *
 ****************************************************************************/

private void display_statistic()
{
    int	    i,j;
    char    dec_str[5];

    for (i = 0; diag_test_list__[i].name != NULL AND i < MAX_TEST; i++) {
	line[0] = '[';
	if (i < 10) {
	    bin_to_dec(i, &dec_str[0]);
	    line[1] = ' ';
	    line[2] = dec_str[0];
	}
	else {
	    bin_to_dec(i, &dec_str[0]);
	    line[1] = dec_str[0];
	    line[2] = dec_str[1];
	}
	line[3] = ']';
	line[4] = '\t';
	strcpy(&line[5], diag_test_list__[i].name);
	for (j = strlen(line); j < 40; j++) line[j] = ' ';
	if (j == 40) line[j] = '\0';
	strcat(line, "RUNS: ");
	bin_to_dec(statistic_table__[i].runs, &line[strlen(line)]);
	for (j = strlen(line); j < 55; j++) line[j] = ' ';
	if (j == 55) line[j] = '\0';
	strcat (line, "FAILS: ");
	bin_to_dec(statistic_table__[i].fails, &line[strlen(line)]);
	print_str(line);
    }
    print_str("");
    strcpy(line,  "DRAM SIZE : 0x");
    bin_to_hex__(dram_size__,  &line[strlen(line)],  'D');
    print_str(line);
#ifdef		SRAM_START
    strcpy(line,  "SRAM SIZE : 0x");
    bin_to_hex__(sram_size__,  &line[strlen(line)],  'D');
    print_str(line);
#endif
#ifdef		DIP_SWITCH
    strcpy(line,  "DIP SWITCH: 0x");
    bin_to_hex__(DIP_SWITCH,  &line[strlen(line)],  'B');
    print_str(line);
#endif
    print_str("");
}


#ifndef LOOP_LIST /* This is the default list of test that run in **
		  ** loop commands                                */
#define LOOP_LIST 0xffff
#endif

/****************************************************************************
 *
 *	get_command()
 *
 ****************************************************************************/

private int get_command(loop, halt_on_error)
		boolean *loop, *halt_on_error;
{
    char    response[80];
    int	    test_list = 0;
    int	    i;

    read_str(response);
    for (i = 0; response[i] == ' '; i++);
    switch (response[i]) {
    /* No meaninig until implemented under the monitor command */
	case 'S': case 's':
	    return STATISTIC;
	case 'D': case 'd':
	    return DEBUG_TOGLE;
#ifdef CACHE
	case 'C':
	    return CACHE_TOGLE;
#endif
	case 'V': case 'v':
	    return VERBOSE_TOGLE;
	case 'A': case 'a':
	    *loop = FALSE;
	    *halt_on_error = FALSE;
	    /*
	     * All possible tests
	     */
	    return LOOP_LIST;
	case 'l':
	    *loop = TRUE;
	    *halt_on_error = TRUE;
	    return (create_list(&response[1]));
	case 'L': 
	    *loop = TRUE;
	    *halt_on_error = TRUE;
	    return LOOP_LIST;	/* All possible tests */
	case 'e':
	    *loop = TRUE;
	    *halt_on_error = FALSE;
	    return (create_list(&response[1]));
	case 'E':
	    *loop = TRUE;
	    *halt_on_error = FALSE;
	    return LOOP_LIST;	/* All possible tests */
	default:
	    *loop = FALSE;
	    *halt_on_error = FALSE;
	    return (create_list(response));
    }	
    
}

/****************************************************************************
 *
 *	create_list()
 *
 ****************************************************************************/

private int create_list (line)
	str	line;
{
    int	    test, cmd = 0;
    char    next_char;
    
			/* Skip at most one blank		  */
	 		/* Two consecutive digits are one number. */
    while (1){
	if (*line == ' ' OR *line == '\t')
	    line ++;
	else if (*line == '\0')
	    return cmd;
	else {
	    if ((*++line == '\0') OR (*line == ' ')) {
	        line --;
	        test = *line - '0';
	    }
	    else {
	        line --;
	        test = 10 * (*line - '0');
	        line ++;
	        test += *line - '0';
	    }
	if (test < 0 OR test >= num_of_test)
	    return SYNTAX_ERROR;
	cmd += 1 << test;
	line ++;
	}
    }
}

extern const char led_tab[];

/****************************************************************************
 *
 *	test_dispatch__()
 *
 ****************************************************************************/

public test_dispatch__(test_list, loop, halt_on_error)
int    test_list;
boolean loop,   halt_on_error;
{
    int	i;
    volatile int j;
    char *response;
    char ch=0;
    char    dec_str[5];

    quit_loop_flag = FALSE;
    do {
	for (i = 0; i < num_of_test; i ++) {
	    if (test_list & (1 << i)) {
		LED(led_tab[i]);
		PRINT_LCD(diag_test_list__[i].name);
		DELAY(0x20000);

		if (verbose_flag) {
		    HOME_CLEAR;
		    display_statistic();
		    strcpy(line, "RUNNING: ");
		    strcat(line, diag_test_list__[i].name);
		    print_str(line);
		}
		response = (* diag_test_list__[i].test_func)();
		statistic_table__[i].runs++;
		/*
		 * Check for error
		 */
		if (response != NULL) {
		    strcpy(line, diag_test_list__[i].name);
		    strcat(line, " ");
		    strcat(line, response);
		    print_str(line); 

		    line[0] = '[';
		    if (i < 10) {
			bin_to_dec(i, &dec_str[0]);
			line[1] = ' ';
			line[2] = dec_str[0];
		    }
		    else {
			bin_to_dec(i, &dec_str[0]);
			line[1] = dec_str[0];
			line[2] = dec_str[1];
		    }
		    line[3] = ']';
		    line[4] = ' ';
		    strcpy(&line[5], "FAILED");

		    PRINT_LCD(line);
		    /* LED(LED_F); */
		    statistic_table__[i].fails++;
		    if (halt_on_error)
			return;
		}
		else {
		    DELAY(0x2000);
		    line[0] = '[';
		    if (i < 10) {
			bin_to_dec(i, &dec_str[0]);
			line[1] = ' ';
			line[2] = dec_str[0];
		    }
		    else {
			bin_to_dec(i, &dec_str[0]);
			line[1] = dec_str[0];
			line[2] = dec_str[1];
		    }
		    line[3] = ']';
		    line[4] = ' ';
		    strcpy(&line[5], "PASSED");
		    if (! loop) {
			print_str(line);
		    }
		    PRINT_LCD(line);
		    LED(LED_P);
		}
		DELAY(0x20000);
	    } /* if */
	    /* Check if User want to exit the loop */
	    if (quit_loop_flag)
		return;
	    if (sio_get_char(&ch))  {
	        if (ch == CTRL_S) {
                    while ( NOT(sio_get_char(&ch) AND (ch == CTRL_Q)) );
	        }
	        if (ch == 'Q' || ch == 'q') {
		    return;
		}
	    }
	}
    } while (loop);
}


/****************************************************************************
 *
 *   Sio_get_char()
 *
 * This function checks if a character is ready on  the serial device.
 * If that is the case it reads it into chp and returns TRUE, otherwise
 * it returns FALSE.
 *
 * The function uses two macros:
 *      READ_CHAR_IS_READY(port)
 *      GET_CHAR(port)
 * This macros are defined in the device definition file.
 *
 ****************************************************************************/
 
private boolean sio_get_char(chp)
char    *chp;
{
    if (READ_CHAR_IS_READY(DIAG_PORT)){
        *chp = GET_CHAR(DIAG_PORT);
        return TRUE;
    }
    return FALSE;
}

 
/****************************************************************************
 *
 *   Sio_put_char()
 *
 * This procedure waits until serial device is ready to accept charcter.
 * It then writes ch into the serial device.
 
 * The routine uses two macros:
 *                     READY_TO_WRITE_CHAR(port)
 *                     PUT_CHAR(port,ch)
 * This macros are defined in the device definition file.
 *
 ****************************************************************************/
 
private void sio_put_char (ch)
char    ch;
{
    while (NOT (READY_TO_WRITE_CHAR(DIAG_PORT)))
        ;
    PUT_CHAR(DIAG_PORT,ch);
}


/****************************************************************************
 *
 *	 print_str()
 *
 ****************************************************************************/

public void print_str(line)
str    line;
{
    int	    i;
    char    ch;
    
    for (i = 0; line[i] != '\0'; i++){		/* Try to read  ^S	*/
        if (sio_get_char(&ch)) {
	    if (ch == CTRL_S) {
                while ( NOT(sio_get_char(&ch) AND (ch == CTRL_Q)) );
	    }
	    if (ch == 'Q' || ch == 'q') {
	       quit_loop_flag = TRUE;
	    }
        }
        sio_put_char(line[i]);			/* Send the charcter	*/
    }
    sio_put_char (CR);				/* End with CR LF sequence */
    sio_put_char(LF);
}

/****************************************************************************
 *
 *	read_str()
 *
 ****************************************************************************/

private void read_str(line)
        str        line;
{
    int	    cur_char;
    char    ch;
 
    for (cur_char = 0; cur_char < 80; cur_char++){
	while (NOT sio_get_char(&ch));
	if (ch == CTRL_S) {	      /* Check for special control character */
            while ( NOT(sio_get_char(&ch) AND (ch == CTRL_Q)) );
	    while (NOT sio_get_char(&ch));
	}
        if (ch == CTRL_H) {
            if (cur_char > 0){
                cur_char -= 2;
		sio_put_char(ch);
		sio_put_char(' ');
		sio_put_char(ch);
            }
        }
        else if (ch == CR) {
	    line[cur_char] = '\0';
	    sio_put_char(ch);
	    sio_put_char(LF);
	    return;
        }
	else {
	    line[cur_char] = ch;
	    sio_put_char(ch);
        }
    } /* for */
}

/*
 * bin_to_hex__() is already defined in Cmon:global_f.c	
 */
#ifndef CMON

const char   hex_char[] = {
        '0', '1', '2', '3',
        '4', '5', '6', '7',
        '8', '9', 'A', 'B',
        'C', 'D', 'E', 'F'
};

/****************************************************************************
 *
 *	bin_to_hex__()
 *
 ****************************************************************************/

public void bin_to_hex__(bin, hex, size)
unsigned bin;
str      hex;
char     size;
{
    int      i, bin_dig, len;
    boolean  non_zero_found;

    non_zero_found = FALSE;		/* Translate Number of charcter */
    switch (size) {			/* acording to size parameter	*/
        case 'B':
            len = 1;
            break;
        case 'W':
            len = 3;
            break;
        case 'D':
            len = 7;
            break;
        case '2':
            len = 1;
            non_zero_found = TRUE;
            break;
        case '4':
            len = 3;
            non_zero_found = TRUE;
            break;
        case '8':
            len = 7;
            non_zero_found = TRUE;
            break;

    }
    for (i = len; i >= 0; i--){
        bin_dig = (bin >> (i * 4)) & 0xf;
        if (non_zero_found OR (bin_dig != 0)) {
            *hex++ = hex_char[bin_dig];
            non_zero_found = TRUE;
        }
    }
    if (NOT non_zero_found) {
        *hex++ = '0';
    }
    *hex = '\0';
} /* bin_to_hex__ */
#endif

/****************************************************************************
 *
 *	bin_to_dec()
 *
 ****************************************************************************/

bin_to_dec(x, dec)
int x;
char *dec;
{
    int d;
    int len = 0;
    char temp_str[20];

    if ( x < 0 )
	return;
    while (1) {
#if (BOARD == VECTOR)
	d = _rem(x, 10);
#else
	d = x % 10; 			/* d is a number between 0-9 */
#endif
	temp_str[len++] = digit[d];
	if (x < 10) {
	    break;
	}
	else {
#if (BOARD == VECTOR)
	    x = _quo(x - d, 10);
#else
	    x = (x - d) / 10;
#endif
	}
    }
    for (len-- ; len >= 0; *dec = temp_str[len--], dec++);
    *dec = '\0';
} /* bin_to_dec */

/****************************************************************************
 *
 *	reverse_bits()
 *
 ****************************************************************************/

reverse_bits(addr, len)
int *addr; 
int len;  
{
int result = 0; 
int mask = 1;  
int val = *addr;

    mask = mask << (len - 1);
    for(; len > 0; len--) {
        if ( val % 2 ) { 	/* If least significant bit is 1 */
            result = result | mask;
        }   
        val = val >> 1;
        mask = mask >> 1;
    }
    return result;
}
 
 
