/******************************************************************************
 *
 *	LCD DIAGNOSTICS FILE
 *
 * History:
 *   +----------+------------+------------------------------------------------+
 *   |   Date   |     by     |     Description                                |
 *   +----------+------------+------------------------------------------------+
 *   |          | GARY       | Written                                        |
 *   +----------+------------+------------------------------------------------+
 *
 * Toshiba TLC671 == Sharp LM16155K == Seiko/Epson M1641
 *
 * To write:
 *    1. set "RS" to "data" (1) or "command" (0)
 *    2. set 4 "LCD" bits to "value"
 *    3. set "E" to trigger (wait 1 usec)
 *    4. "E" to low (and wait 1 usec)
 *
 *   SWIFT and VECTOR has a 4 bit interface to the LCD data register.
 *   All access need two 4 bit wide write cycles most significant
 *   nibble first.
 *
 *****************************************************************************/

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

#define		CURSOR_HOME	0x2
#define		DISPLAY_OFF	0x8
#define		DISPLAY_ON	0xc
#define		DSP_CLEAR	0x1
#define		AUTO_INC	0x6
#define		INIT		0x3
#define		LOAD_LS_DSP	0x80
#define		LOAD_MS_DSP	0xc0

#if ((BOARD == VECTOR) OR (BOARD == CG160LX) OR (BOARD == VIPER))
						/* 4 bits interface	*/
#    define	LCD_BW		0x28
#else						/* 8 bits interface	*/
#    define	LCD_BW		0x38
#endif


/*  forward functions */
/**********************/

public  void  write_lcd__();
public  void  print_lcd__();
public  void  cmnd_lcd__();
public  void  init_lcd__();


/***************************************************************************
 *
 *	write_lcd__()
 *
 *  This function use`s two macros defined in <board>_def.h.
 *  It writes two nibbles of 4 bits each, to the lcd in the following sequence:
 *   LCD_BIT_CLEAR(LCDRS) 
 *   LCD_BYTE_SET(nibble)
 *   LCD_BIT_SET(LCE)		DELAY
 *   LCD_BIT_CLEAR(LCE)		DELAY
 *
 **************************************************************************/

public  void  write_lcd__(val)
int val;
{
    SET_LCD_DATA((val >> 4) & 0xf);
    SET_LCD_DATA(val & 0xf);
}


/***************************************************************************
 *
 *	print_lcd__()
 *
 *  This function loads a 16 charecter string (as two strings of eight
 *  charecters) to the LCD ram and displays it.
 *
 **************************************************************************/

public  void  print_lcd__(s)
char *s;
{
    char c, i;


    cmnd_lcd__(DISPLAY_OFF); 	
    DELAY(1000);
    cmnd_lcd__(CURSOR_HOME);
#ifndef DEBUG
    DELAY(1000);
#else
    DELAY(10000);
#endif

    cmnd_lcd__(LOAD_LS_DSP);		/* load 8 LS digits of inner LCD RAM */
    DELAY(5000);
    for (i=0; i<16; i++) {
	if (i == 8) { 
	    cmnd_lcd__(LOAD_MS_DSP);	/* load 8 MS digits of inner LCD RAM */
	    DELAY(5000);
	}
	c = (*s) ? *s++ : ' ';       /* if past end of string then blankfill*/
	write_lcd__(c);
	DELAY(1000);
    }
    cmnd_lcd__(DISPLAY_ON);
}
/***************************************************************************
 *
 *	cmnd_lcd__()
 *
 *  This function writes a command to the LCD as in the function write_lcd__().
 *  The only difference is in one memory maped I/O bit in LCDRS.
 *
 **************************************************************************/

public  void  cmnd_lcd__(val)
    int val;
{
    SET_LCD_CMND((val >> 4) & 0xf);
    SET_LCD_CMND(val & 0xf);
}


/***************************************************************************
 *
 *	init_lcd__()
 *
 *  This function initiates the LCD according to the LCD spec`.
 *
 **************************************************************************/
public  void  init_lcd__()
{
#if (BOARD == CG160LX)
    CFR_SET_ROM_WAIT(2);          	/* set ROM speed to 2 wait state */
#endif

#if (BOARD == VIPER)
    DELAY(250000);			 /* Init LCD to a 4 bit interface */
    cmnd_lcd__(0x30);		
    DELAY(10000);
    cmnd_lcd__(0x30);		
    DELAY(2500);
    cmnd_lcd__(0x30);
    DELAY(2500);
    cmnd_lcd__(0x20);
    DELAY(2500);
    cmnd_lcd__(LCD_BW);
    DELAY(2500);
    cmnd_lcd__(DISPLAY_OFF);
    DELAY(2500);
    cmnd_lcd__(DSP_CLEAR);
    DELAY(2500);
    cmnd_lcd__(AUTO_INC);
    DELAY(2500);
#else
    DELAY(6000);			/* Init LCD to a 4 bit interface */
    cmnd_lcd__(INIT);		
#ifndef DEBUG
    DELAY(1000);
#else
    DELAY(10000);
#endif
    cmnd_lcd__(INIT);		
    DELAY(1000);
    cmnd_lcd__(INIT);
    cmnd_lcd__(0x2);
    cmnd_lcd__(LCD_BW);
    cmnd_lcd__(DISPLAY_OFF);
    cmnd_lcd__(DSP_CLEAR);
    cmnd_lcd__(AUTO_INC);
#endif
}


/****************************************************************************
 *
 * Test_lcd__()
 *
 *  This is the main LCD test routin. It performs a walk sqaure on the LCD
 *
 ***************************************************************************/

char buf[20];


public test_lcd__()
{
    int i, j;


    for (i=0; i < 16; i++) {
	for (j=0; j< 16; j++) {
	    if( i == j) {
		buf[j] = 0xff;
	    }
	    else {
		buf[j] = ' ';
	    }
	}
	buf[j] = '\0';
	print_lcd__(buf);
#ifndef DEBUG
	DELAY(LCD_ROM_DELAY);
#else
	DELAY(LCD_RAM_DELAY);
#endif
    }
    return NULL;
}
