/*
 * indicator - wh1602p
 * controller - ks0066 
 * E - strobe 1/1 (d-type 25/centronics)
 * RS - select printer 17/36
 * RW - auto linefeed 14/14
 */

#include <stdlib.h>
#include <stdio.h>
#include <sys/io.h>
#include <unistd.h>


#define LPT_BASE	0x378
#define LPT_CTRL	(LPT_BASE+2)
#define LPT_STAT	(LPT_BASE+1)

void set_rs()
{
	unsigned char ch = inb(LPT_CTRL);
	ch &= ~8;
	outb( ch, LPT_CTRL);
}

void clr_rs()
{
	unsigned char ch = inb(LPT_CTRL);
	ch |= 8;
	outb( ch, LPT_CTRL);
}

void clr_rw()
{
	unsigned char ch = inb(LPT_CTRL);
	ch |= 2;
	outb( ch, LPT_CTRL);
}

void set_e()
{
	unsigned char ch = inb(LPT_CTRL);
	ch &= ~1;
	outb( ch, LPT_CTRL);
}

void clr_e()
{
	unsigned char ch = inb(LPT_CTRL);
	ch |= 1;
	outb( ch, LPT_CTRL);
}

void toggle_e()
{
	set_e();
	//usleep(1);
	clr_e();
	usleep(50);
}

void lcd_write(unsigned char data, int rs)
{
	clr_rw();
	rs ? set_rs():clr_rs();
	outb( data, LPT_BASE );
	toggle_e();
}

void lcd_comm( unsigned char data )
{
	lcd_write( data, 0 );
}

void lcd_data( unsigned char data )
{
	lcd_write( data, 1 );
}
	

void lcd_char( char ch )
{
	lcd_data( ch );
}

void lcd_str( const char *str)
{
	while( *str )
		lcd_char(*str++);
}


void set_line( int line )
{
	unsigned char addr = 0x00;
	addr = line  ? 0x44:0x00;
	addr |= 128;
	lcd_comm( addr );
}

void lcd_init()
{
	clr_rw();
	clr_rs();
	lcd_comm( 0x38 );
	usleep(50);
	lcd_comm( 0x0C );
	usleep(50);
	lcd_comm( 0x01 );
	usleep(2000);
	lcd_comm(0x06);
}

void lcd_gotoxy( int x, int y )
{
	unsigned char addr;
	addr = y  ? 0x40:0x00;
	addr |= 128;
	addr += x;
	lcd_comm( addr );
}

int main(int argc, char *argv[])
{
	unsigned int port = LPT_BASE;
	unsigned char value;
	ioperm(LPT_BASE,3,1);
#if 0
	switch( *(argv[1]) )
	{
		case '0': port = LPT_BASE; break;
		case '1': port = LPT_CTRL; break;
		case '2': port = LPT_STAT; break;
	}
	if( *(argv[2]) == 'r' )
	{
		printf("%X\n", inb(port));
	}
	else
	{
		value = atoi(argv[2]);
		outb(value, port);
	}
#endif
	
	lcd_init();
#if 1
	char buffer[20];
	unsigned char i = 0;
	int c=0;
	lcd_gotoxy(0,0);
	for(i=128; i<254; i++ )
	{
		lcd_char(i);
		c++;
		sprintf(buffer,"%X %d", i,i);
		lcd_gotoxy(0,1);
		lcd_str(buffer);
		if(c==16)
		{
			c=0;
			lcd_gotoxy(0,0);
		}
		else
		{
			lcd_gotoxy(c,0);
		}
		usleep(200000);
	}
#endif
	ioperm(LPT_BASE,3,0);
}
