/*
 * lcdprint.c - initialises and prints characters to
 * HD44780 compatible LCD (Z4172 from Dick Smiths NZ)
 *
 * Donn Morrison, March 2005, donn.morrison@gmail.com
 *
 * If argument is supplied, that string is printed.
 * If no arguments, lcdprint enters curses mode and
 * any characters typed are echoed to the LCD.
 * 
 * Compile: gcc lcdprint.c -o lcdprint -lcurses
 *
 */

#include <stdio.h>
#include <unistd.h>
#include <asm/io.h>
#include <curses.h>

#define BASEPORT 0x0378 /* lp0 */

int lcd_putc(char c);
int lcd_init();
int lcd_print(char *string);
int outb4(char c, int port);

int main(int argc, char *argv[])
{
	/* Get access to the ports */
	if (ioperm(BASEPORT, 3, 1)) {perror("ioperm"); exit(1);}

	lcd_init();

	if(argc == 2)
	{
		lcd_print(argv[1]);
	}
	else
	{
		/* curses stuff */
		initscr();
		cbreak();

		char c;
		while((c=getch()) != EOF)
		{
			if(c < ' ' || c > '~') continue;
		/*	printf("0x%02x",c); */
			lcd_putc(c);
		}

		endwin();

	}

	/* We don't need the ports anymore */
	if (ioperm(BASEPORT, 3, 0)) {perror("ioperm"); exit(1);}

	exit(0);
}

int lcd_init()
{
	/* wait for voltage to rise */
	usleep(30000);

	/* bits in the following comments 
	 * surrounded in [] are non-essential
	 * for the operation.
	 * x = don't care */

	/* function set */
	outb(3, BASEPORT+2);
	outb(56, BASEPORT); /* 0011 [10xx] */
	outb(2, BASEPORT+2);
	usleep(39);
	
	/* display on */
	outb(3, BASEPORT+2);
	outb(12, BASEPORT); /* 0000 1[100] (no cursor no blink) */
	outb(2, BASEPORT+2);
	usleep(39);

	/* clear display */
	outb(3, BASEPORT+2);
	outb(1, BASEPORT); /* 0000 0001 */
	outb(2, BASEPORT+2);
	usleep(1530);

	/* entry mode set */
	outb(3, BASEPORT+2);
	outb(6, BASEPORT); /* 0000 01[10] */
	outb(2, BASEPORT+2);
	usleep(39);

	return 0;
}

int lcd_putc(char c)
{
	if(c == 0x7f)
	{
		char addr = 0;
		/* backspace */

		/* put r/w high */
		outb(1, BASEPORT+2);
		/* signal enable (latch data) */
		outb(2, BASEPORT+2);
		outb(3, BASEPORT+2);
		usleep(39);

		addr = inb(BASEPORT);
		printf("addr=0x%02x\n", addr);

		/* move cursor back */
		outb(3, BASEPORT+2);
		outb(addr-1+128, BASEPORT);
		outb(2, BASEPORT+2);
		usleep(39);

	}
/*	printf("putting 0x%02xh %d %c\n",c,c,c);*/
	outb(14, BASEPORT+2);
	outb(c, BASEPORT);
	outb(11, BASEPORT+2);
	usleep(43);

	return 0;
}

int lcd_print(char *string)
{
	int i=0;
	for(i=0;i<strlen(string);i++)
	{
		lcd_putc(string[i]);
	}

	return 0;
}
