#include <string.h>
#include <stdio.h>
#include <io.h>
#include <compiler.h>		// used to fix AVR-GCC bug with stack pointer  


#include <dev/debug.h>

#include <dev/uartavr.h>
#include <dev/irqreg.h>

#include <sys/heap.h>
#include <sys/thread.h>
#include <sys/timer.h>



#define dataport  PORTB
#define ctrlport  PORTD

#define RS PD0
#define RW PD2
#define E  PD4




/** xor mask for LPT register **/
#define Mask 11

/** DISPINIT **/
#define DISPINIT 0x38


void InitLCD(void);
void WaitDispReady(void);
void WriteData(int d);
void WriteCtrlDirect(int d);
void WriteCtrl(int d);
void clearDisplay(void);
void CursorHome(void);
void moveCursor(int line, int pos);
void Textout(u_char* s);
void TextoutXY(u_char* s, int line, int pos);


/****************************
 * Main function
 ****************************/
int main(void)
{

	
	
	// I/O direction of port B 
    outp(0xFF, DDRB); //all pins as outputs
	// I/O direction of port D 
    outp(0xFF, DDRD); //all pins as outputs

    // port B outputs to LOW
	outp(0x00, PORTB);
    // port D outputs to LOW
    outp(0x00, PORTD);
	

    InitLCD();
	Textout("Hello");
	TextoutXY("world!",2,6);
	
	// Nut/OS never expects a thread to return. So we enter an endless loop here. 
	for (;;) 
	{
	 NutSleep(100);
	}

}


/**
* @brief Causes a short delay (ca. 3ms)
* @date 1.3.2005 First version
**/
void WaitDispReady(void)
 {
 NutSleep(3);
 }

/**
* @brief Sends a single character to the display.\n
* Character is placed at current cursor position.
* @param d (unsigned char) is the character to be send.
* @date 1.3.2005 First version
**/
void WriteData(int d)
 {
 WaitDispReady();
 outp(d, dataport);

 sbi(ctrlport, RS);  //RW, E low   RS high
 
 sbi(ctrlport, E);   //RW low      RS, E high
 
 cbi(ctrlport, E);   //RW, E low   RS high
 }

/**
* @brief Sends a control command to the display.
* @param d (unsigned char) is the command to be send.\n
* @note For a list of commands see datasheet "LC-Display Barton MDL16265"\n
* Display datasheets available at <A HREF="www.pollin.de">
* @date 1.3.2005 First version
**/
void WriteCtrlDirect(int d)
 {
 outp(d, dataport);

 cbi(ctrlport, RS);  //RS, E, RW low
 sbi(ctrlport, E);   //E high
 cbi(ctrlport, E);   //RS, E, RW low
 
 }

/**
* @brief Equal to WriteCtrlDirect, but waits for display to be ready
* @see WriteCtrlDirect(unsigned char d)
* @see WaitDispReady(void)
* @date 1.3.2005 First version
**/
void WriteCtrl(int d)
 {
 WaitDispReady();
 WriteCtrlDirect(d);
 }


/**
* @brief Clears display screen
* @date 1.3.2005 First version
**/
void clearDisplay(void)
 {
 WriteCtrl(1);
 }

/**
* @brief Moves cursor to 1st line, 1st column
* @date 1.3.2005 First version
**/
void CursorHome(void)
 {
 WriteCtrl(2);
 }

/**
* @brief Moves cursor to specified position
* @param line (unsigned char) specifies cursor line [1,2]
* @param line (unsigned char) specifies cursor column [1..16]
* @date 1.3.2005 First version
**/
void moveCursor(int line, int pos)
 {
 WriteCtrl(64+(64*line)+pos);
 }

/**
* @brief Writes a string on display.\n
* at current cursor position.
* @param s (array of char) string to be writen.\n
* @date 1.3.2005 First version
**/
void Textout(u_char* s)
 {
 unsigned char i = 0;
 unsigned char c = 0;

 //max 16 charakters per line
 for (i=0; i<16; i++)
  {
  c = s[i];
  if (c== '\0') break;
  WriteData(c);
  }
 }


/**
* @brief Writes a string on display.\n
* at specified position.
* @param s (array of char) string to be writen.\n
* @param line specifies line [1,2]
* @param line specifies column [1..16]
* @date 1.3.2005 First version
**/
void TextoutXY(u_char* s, int line, int pos)
 {
 int i = 0;
 int c = 0;

 moveCursor(line, pos);
 //max 16 charakters per line
 for (i=0; i<16; i++)
  {
  c = s[i];
  if (c== '\0') break;
  WriteData(c);
  }
 }


/**
* @brief Initiates display
* @date 1.3.2005 First version
**/
void InitLCD(void)
 {
 WriteCtrlDirect(DISPINIT);
 NutSleep(5);
 WriteCtrlDirect(DISPINIT);
 NutSleep(1);
 WriteCtrlDirect(DISPINIT);
 clearDisplay();
 CursorHome();
 //EntryMode
 WriteCtrl(6);
 WriteCtrl(6);
 //Display on
 WriteCtrl(12);
 WriteCtrl(12);
 //Set DD-RAM
 WriteCtrl(128);
 }

