/* LCD interface  Rob Chapman  Dec 9, 1996 */


#include <stdio.h>

#include <string.h>

#include <hc12.h>

#include "maxrtos.h"

#include "lcd.h"


// port interface to LCD: one or the other

// Either LCDCR and LCDDR as byte memory locations or

// Port J 0-7 as the data bus for the LCD d0-d7 and

// Port D 7,5,3 is the control lines R/W, D/C, E



// lcd queue management

QUEUE(500,lcdq); 	/* queue of data and commands for the LCD display */

	

void lcd_data(Cell data)  /* queue up data for lcd display */

{

	pushq(data,&lcdq);

}


void lcd_cmd(Cell cmd)  /* queue up command for lcd display */

{

	pushq(cmd | 0x8000,&lcdq); /* tagged for later */

}


Flag lcd_ready(void)  /* check to see if lcd display is ready */

{

	return((lcd_read(LCR) & 0x80) == 0);

}


void feed_lcd(void)  /* send data or commands to lcd display when possible */

{

	if ((queryq(&lcdq) != 0) && (lcd_ready() != 0))

	{

		Cell data_cmd = pullq(&lcdq);

		

		if ((data_cmd & 0x8000) == 0)

			lcd_write(LDR,(Byte)data_cmd);

		else

			lcd_write(LCR,(Byte)data_cmd);

	}

	run(feed_lcd);

}


void run_lcd(void)  /* run the lcd display machine */

{

	int i;


	MODE &= ~1;		// enable port E

	PORTD = R_W;	// default to read and disabled

	DDRD = R_W | LDR | ENABLE;	// setup the control port

	zeroq(&lcdq);

	run(feed_lcd);

	for (i=0;i<2;i++)

		lcd_cmd(0x38);  /* reset: 8 bits, 2 lines lcd */

	lcd_cmd(0x06);  /* cursor shift, incremet counter */

	lcd_cmd(CURSOR_OFF);  /* display on, cursor off */

	lcd_clear();  /* clear display, set cursor home */

}


void lcd_type(char addr[], Cell count)  /* send an array of bytes */

{

	for(;count != 0;count--)

		lcd_data((Cell)(Byte)*addr++);

}


void lcd_stype(char *s)

{

	lcd_type(s, strlen(s));

}


Cell lcd_row, lcd_col;


void lcd_set(Cell row, Cell column)  /* set the cursor position */

{

	lcd_row = row;

	lcd_col = column;


	switch(row)	// encode the row bits for character lines for x16,20

	{ // this would be faster and vectorable if an array was used

		case 0:  row = 0x80;

				 break;

		case 1:  row = 0xC0;

				 break;

		case 2:  row = 0x94;

				 break;

	    default: row = 0xD4;

	}

	lcd_cmd(row+column);

}


void lcd_clear(void)  /* clear the lcd dislay */

{

	lcd_cmd(CLEAR_LCD);

}

