#include "../PPort/PPort.h"
#include <windows.h>

//----------------------------------------------------------------------------------------------
//--Class Definition----------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
class LCD
{
public:

	LCD();
	
	void SetLCD(unsigned char height, unsigned char width, unsigned char databus);
	//Opens up the parallel port connection and initializes the LCD w/ the three specified parameters

	void ClearDisplay();
	//Clears the display

	void CursorHome();
	//Returns the cursor to the home position

	void EntryModeSet(bool IncDec = 1, bool shift = 0);
	//If IncDec = 1 (increment) then the cursor moves right or the text left
	//   IncDec = 0 (decrement) then the cursor moves left, or the text right
	//  S (shift) = 0 then cursor move, S = 1 means the text moves

	void DisplayOnOffControl(bool displayIsOn, bool cursorIsOn, bool cursorBlinks);
	//Turn on or off the whole display, the curso, and whether or not the cursor blinks

	void CursorDisplayShift(bool dispShift, bool right);
	//shift = 1 and text moves, shift = 0 and the cursor moves
	//right = 1 and it's to the right, right = 0 and its to the left

	void SetInterfaceLength(bool dataBus = 1, bool numOfLines = 1, bool charFont = 0);
	//(1,1,1) = (8 bit, 2 line, 5x10);  (0,0,0) = (4 bit, 1 line, 5x7)

	bool SetCGRamAdd(unsigned char address);
	//Sets the address in Character Generator Ram that you will be reading or writing to
	// returns false if address is out of range

	bool SetDDRamAdd(short address);
	//Sets the address in Display Data Ram that you will be reading or writing to

	bool ReadBFAC();
	//NOT IMPLEMENTED in this version; Reads the busy flag and address counter

	bool WriteRam(unsigned char data);
	//writes the data to the selected CG Ram address

	unsigned char ReadRam();
	//NOT IMPLEMENTED in this version; reads the ram and returns it

private:

	PPort port;	//the parallel port

	short width, height;	//the width and height of the LCD

	short cursorPos [40][4];	//the current position of the cursor, [horizontal][vertical]
};

//----------------------------------------------------------------------------------------------
//--Class Implementation------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------

LCD::LCD()
{
	SetLCD(1,1,1);
}
//----------------------------------------------------------------------------------------------
void LCD::SetLCD(unsigned char height, unsigned char width, unsigned char databus)
//so far none of the parameters are implemented, but for now the defaults are fine
//databus so far must be 8 bits, I don't feel like writing a 4bit interface yet
{
	//To initialize, wait 15ms from power on,														|X|
	//  write 0x30 wait 5ms, 0x30 wait 5ms, 0x30 wait 160us, then set operating characteristics...	|X|
	//	+Write interface length																		|X|
	//	+Write 0x010 to turn off display, or call the function										|X|
	//	+Write 0x001 to clear display																|X|
	//	+Write EntryModeSet																			|X|
	//	+Write DisplayOnOffControl																	|X|
	port.SetPPort();
	_sleep(15);
	port.SetByte(0x30);
	port.StrobeEPin();
	_sleep(5);
	port.StrobeEPin();
	_sleep(1);

	SetInterfaceLength(1,0,0); //defaults to 8 bit, 1 line, 5x7
	
	DisplayOnOffControl(0,0,0);

	ClearDisplay();

	EntryModeSet();

	DisplayOnOffControl(1,1,0);

	port.ChangeToInstructionRegister();
}
//----------------------------------------------------------------------------------------------
void LCD::ClearDisplay()
{
	port.SetByte(0);
	port.SetBit(0);
	port.StrobeEPin();
	_sleep(5);
}
//----------------------------------------------------------------------------------------------
void LCD::CursorHome()
{
	port.SetByte(0);
	port.SetBit(1);
	port.StrobeEPin();
	_sleep(5);
}
//----------------------------------------------------------------------------------------------
void LCD::EntryModeSet(bool IncDec, bool shift)
{
	port.SetByte(0);
	port.SetBit(2);
	if(IncDec)
		port.SetBit(1);
	if(shift)
		port.SetBit(0);
	port.StrobeEPin();
	_sleep(1);
}
//----------------------------------------------------------------------------------------------
void LCD::DisplayOnOffControl(bool displayIsOn, bool cursorIsOn, bool cursorBlinks)
{
	port.SetByte(0);
	port.SetBit(3);
	if(displayIsOn)
		port.SetBit(2);
	if(cursorIsOn)
		port.SetBit(1);
	if(cursorBlinks)
		port.SetBit(0);
	port.StrobeEPin();
	_sleep(1);
}
//----------------------------------------------------------------------------------------------
void LCD::CursorDisplayShift(bool dispShift, bool right)
{
	port.SetByte(0);
	port.SetBit(4);
	if(dispShift)
		port.SetBit(3);
	if(right)
		port.SetBit(1);
	port.StrobeEPin();
	_sleep(1);
}
//----------------------------------------------------------------------------------------------
void LCD::SetInterfaceLength(bool dataBus, bool numOfLines, bool charFont)
{
	port.SetByte(0);
	port.SetBit(5);
	if(dataBus)
		port.SetBit(4);
	if(numOfLines)
		port.SetBit(3);
	if(charFont)
		port.SetBit(2);
	port.StrobeEPin();
	_sleep(1);
}
//----------------------------------------------------------------------------------------------
bool LCD::SetCGRamAdd(unsigned char address)
{
	port.SetByte(0);
	if(address>63)
		return false;
	port.SetByte(address);
	port.SetBit(6);
	port.StrobeEPin();
	_sleep(1);
	return true;
}
//----------------------------------------------------------------------------------------------
bool LCD::SetDDRamAdd(short address)
{
	port.SetByte(0);
	if(address>127)
		return false;
	port.SetByte(address);
	port.SetBit(7);
	port.StrobeEPin();
	_sleep(1);
	return true;
}
//----------------------------------------------------------------------------------------------
bool LCD::WriteRam(unsigned char data)
{
	port.SetByte(0);
	port.ChangeToDataRegister();
	if(data>255)
		return false;
	port.SetByte(data);
	port.StrobeEPin();
	_sleep(1);
	port.ChangeToInstructionRegister();
	return true;
}
//----------------------------------------------------------------------------------------------

