/*
 * Linux User & Developer LCD interfacing example code.
 *
 */

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

#define BASE			0x378
#define BASE_DATA		(BASE+0)
#define BASE_STATUS		(BASE+1)
#define BASE_CONTROL		(BASE+2)

#define ENABLE_ON               0
#define ENABLE_OFF              1

#define WRITE_DATA              2
#define READ_DATA               0

#define I_COMMAND               0
#define D_COMMAND               4

#define COMMAND_FUNCTION_SET	0x38
#define COMMAND_ENTRY_MODE      0x06
#define COMMAND_DISPLAY_ON      0x18
#define COMMAND_CLEAR_DISPLAY           0x01

void function_set(void);
void display_on(void);
void lcd_init(void);
void lcd_printf(const char *string);

static inline void instruction_write(void) {

  outb(I_COMMAND|WRITE_DATA, BASE_CONTROL);
  outb(ENABLE_ON|I_COMMAND|WRITE_DATA, BASE_CONTROL);
  usleep(1);
  outb(ENABLE_OFF|I_COMMAND|WRITE_DATA, BASE_CONTROL);
  usleep(1);

}

void function_set(void) {

  outb(COMMAND_FUNCTION_SET, BASE_DATA);	// Set function.
  instruction_write();
}

void entry_mode(void) {

  outb(COMMAND_ENTRY_MODE, BASE_DATA);
  instruction_write();
}

void display_on(void) {
  
  outb(COMMAND_DISPLAY_ON, BASE_DATA);
  instruction_write();

}

void clear_display(void) {

  outb(COMMAND_CLEAR_DISPLAY, BASE_DATA);
  instruction_write();

}

void lcd_init(void) {

	ioperm(BASE, 3, 1);		// request IO access
	function_set();
	function_set();
	entry_mode();
	display_on();
	clear_display();
}

void lcd_putchar(const char data) {

  outb(D_COMMAND|WRITE_DATA, BASE_CONTROL);
  outb(data, BASE_DATA);
  outb(ENABLE_ON|D_COMMAND|WRITE_DATA, BASE_CONTROL);
  usleep(1);
  outb(ENABLE_OFF|D_COMMAND|WRITE_DATA, BASE_CONTROL);
  usleep(1);

}

void lcd_printf(const char *string) {

  unsigned int i = 0;

  for (i=0;i<strlen(string);i++)
    lcd_putchar(string[i]);

}

int main(int argc, char **argv) {
	
	printf("Linux User & Developer LCD interfacing example.\n");
	printf("Initialising display...");
	lcd_init();
	printf("done\n");
	printf("Printing Hello World text...");
	lcd_printf("Linux User");
	printf("done\n");

}

