#ifndef Tristans_LCD_lib_h
#define Tristans_LCD_lib_h

#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>

#ifndef LCD_LINES
#error "LCD_LINES was not declared"
#define LCD_LINES
#endif

#ifndef _5x10_1_OR_5x7_0_DOTMATRIX
#error "_5x10_1_OR_5x7_0_DOTMATRIX was not defined"
#define _5x10_1_OR_5x7_0_DOTMATRIX
#endif

//PORTS & PINS
#ifndef PORT_REG_RS_LCD
#error "PORT_REG_RS_LCD was not defined"
#define PORT_REG_RS_LCD
#endif
#ifndef REG_NR_RS_LCD
#error "REG_NR_RS_LCD was not defined"
#define REG_NR_RS_LCD
#endif
#ifndef DIR_REG_RS_LCD
#error "DIR_REG_RS_LCD was not defined"
#define DIR_REG_RS_LCD
#endif

#ifndef PORT_REG_ENABLE_LCD
#error "PORT_REG_ENABLE_LCD was not defined"
#define PORT_REG_ENABLE_LCD
#endif
#ifndef REG_NR_ENABLE_LCD
#error "REG_NR_ENABLE_LCD was not defined"
#define REG_NR_ENABLE_LCD
#endif
#ifndef DIR_REG_ENABLE_LCD
#error "DIR_REG_ENABLE_LCD was not defined"
#define DIR_REG_ENABLE_LCD
#endif

#ifndef PORT_REG_DATAPIN4_LCD
#error "PORT_REG_DATAPIN4_LCD was not defined"
#define PORT_REG_DATAPIN4_LCD
#endif
#ifndef DIR_REG_DATAPIN4_LCD
#error "DIR_REG_DATAPIN4_LCD was not defined"
#define DIR_REG_DATAPIN4_LCD
#endif
#ifndef REG_NR_DATAPIN4_LCD
#error "REG_NR_DATAPIN4_LCD was not defined"
#define REG_NR_DATAPIN4_LCD
#endif

#ifndef PORT_REG_DATAPIN5_LCD
#error "PORT_REG_DATAPIN5_LCD was not defined"
#define PORT_REG_DATAPIN5_LCD
#endif
#ifndef DIR_REG_DATAPIN5_LCD
#error "DIR_REG_DATAPIN5_LCD was not defined"
#define DIR_REG_DATAPIN5_LCD
#endif
#ifndef REG_NR_DATAPIN5_LCD
#error "REG_NR_DATAPIN5_LCD was not defined"
#define REG_NR_DATAPIN5_LCD
#endif

#ifndef PORT_REG_DATAPIN6_LCD
#error "PORT_REG_DATAPIN6_LCD was not defined"
#define PORT_REG_DATAPIN6_LCD
#endif
#ifndef DIR_REG_DATAPIN6_LCD
#error "DIR_REG_DATAPIN6_LCD was not defined"
#define DIR_REG_DATAPIN6_LCD
#endif
#ifndef REG_NR_DATAPIN6_LCD
#error "REG_NR_DATAPIN6_LCD was not defined"
#define REG_NR_DATAPIN6_LCD
#endif

#ifndef PORT_REG_DATAPIN7_LCD
#error "PORT_REG_DATAPIN7_LCD was not defined"
#define PORT_REG_DATAPIN7_LCD
#endif
#ifndef DIR_REG_DATAPIN7_LCD
#error "DIR_REG_DATAPIN7_LCD was not defined"
#define DIR_REG_DATAPIN7_LCD
#endif
#ifndef REG_NR_DATAPIN7_LCD
#error "REG_NR_DATAPIN7_LCD was not defined"
#define REG_NR_DATAPIN7_LCD
#endif
/*
 * LCD-4 bit modus Test o-Lib.c
 *
 * Created: 12.06.2016 18:50:57
 * Author : Tristan
 */
void enable_LCD_4bit_library_function();
void initialize_LCD_4bit(void);

void write_data_to_LCD_as_byte (unsigned char);
void write_data_to_LCD_as_string (char*);
void set_DDRAM_address_LCD (unsigned char);
void set_CGRAM_address_LCD (unsigned char);
void clear_display_LCD (void);
void return_home_LCD (void);
void display_on_off_control_LCD (unsigned char, unsigned char, unsigned char);
void cursor_or_display_shift_LCD (unsigned char, unsigned char);

void initialize_LCD_4bit(void)
{
	DIR_REG_RS_LCD |= (1<<REG_NR_RS_LCD);
	DIR_REG_ENABLE_LCD |= (1<<REG_NR_ENABLE_LCD);
	DIR_REG_DATAPIN7_LCD |= (1<<REG_NR_DATAPIN7_LCD);
	DIR_REG_DATAPIN6_LCD |= (1<<REG_NR_DATAPIN6_LCD);
	DIR_REG_DATAPIN5_LCD |= (1<<REG_NR_DATAPIN5_LCD);
	DIR_REG_DATAPIN4_LCD |= (1<<REG_NR_DATAPIN4_LCD);
	
	PORT_REG_RS_LCD &= ~(1<<REG_NR_RS_LCD);
	PORT_REG_ENABLE_LCD &= ~(1<<REG_NR_ENABLE_LCD);
	
	_delay_ms(40);
	
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
	
	unsigned char LCD_lines_help_var = 1;
	unsigned char function_set_help_variable = (0x00|(LCD_lines_help_var<<3)|(_5x10_1_OR_5x7_0_DOTMATRIX<<2));
	function_set_help_variable = 0x80;
	unsigned char initializing_values[] = {0x30, 0x30, 0x30, 0x20, 0x20, function_set_help_variable, 0x00, 0x80, 0x00, 0x10, 0x00, 0x60};
	unsigned char help_var = 0;
	for (unsigned char counter_var=0; counter_var<12; counter_var++)
	{
		(initializing_values[counter_var] & (1<<7)) ? (help_var = 1) : (help_var = 0);
		PORT_REG_DATAPIN7_LCD |= (help_var << REG_NR_DATAPIN7_LCD);
		(initializing_values[counter_var] & (1<<6)) ? (help_var = 1) : (help_var = 0);
		PORT_REG_DATAPIN6_LCD |= (help_var << REG_NR_DATAPIN6_LCD);
		(initializing_values[counter_var] & (1<<5)) ? (help_var = 1) : (help_var = 0);
		PORT_REG_DATAPIN5_LCD |= (help_var << REG_NR_DATAPIN5_LCD);
		(initializing_values[counter_var] & (1<<4)) ? (help_var = 1) : (help_var = 0);
		PORT_REG_DATAPIN4_LCD |= (help_var << REG_NR_DATAPIN4_LCD);
		
		PORT_REG_ENABLE_LCD |= (1<<REG_NR_ENABLE_LCD);
		PORT_REG_ENABLE_LCD &= ~(1<<REG_NR_ENABLE_LCD);
		_delay_ms(50);
		
		PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
		PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
		PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
		PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
	}
}

void enable_LCD_4bit_library_function (void)
{
	PORT_REG_ENABLE_LCD |= (1<<REG_NR_ENABLE_LCD);
	PORT_REG_ENABLE_LCD &= ~(1<<REG_NR_ENABLE_LCD);
	_delay_us(600);
}

void clear_display_LCD(void)
{
	PORT_REG_RS_LCD &= ~(1<<REG_NR_RS_LCD);
		
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();
	_delay_ms(20);
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD |= (1<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();
	_delay_ms(20);
}

void return_home_LCD (void)
{
	PORT_REG_RS_LCD &= ~(1<<REG_NR_RS_LCD);
	
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();
	_delay_ms(20);
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD |= (1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();
	_delay_ms(20);
}

void display_on_off_control_LCD(unsigned char enable_display_LCD, unsigned char enable_cursor_LCD, unsigned char enable_blinking_character_LCD)
{
	PORT_REG_RS_LCD &= ~(1<<REG_NR_RS_LCD);
	
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();
	PORT_REG_DATAPIN7_LCD |= (1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD |= (enable_display_LCD<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD |= (enable_cursor_LCD<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD |= (enable_blinking_character_LCD<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();
}

void cursor_or_display_shift_LCD(unsigned char cursor_0_or_display_1, unsigned char right_1_or_left_0)
{
	PORT_REG_RS_LCD &= ~(1<<REG_NR_RS_LCD);
		
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD |= (1<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();
	PORT_REG_DATAPIN7_LCD |= (cursor_0_or_display_1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD |= (right_1_or_left_0<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();
}

void set_CGRAM_address_LCD(unsigned char CGRAM_adress_variable)
{
	unsigned char help_var = 0;
	PORT_REG_RS_LCD &= ~(1<<REG_NR_RS_LCD);
	
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
	
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD |= (1<<REG_NR_DATAPIN6_LCD);
	(CGRAM_adress_variable & (1<<5))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN5_LCD |= (help_var<<REG_NR_DATAPIN5_LCD);
	(CGRAM_adress_variable & (1<<4))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN4_LCD |= (help_var<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();
	
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
	
	(CGRAM_adress_variable & (1<<3))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN7_LCD |= (help_var<<REG_NR_DATAPIN7_LCD);
	(CGRAM_adress_variable & (1<<2))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN6_LCD |= (help_var<<REG_NR_DATAPIN6_LCD);
	(CGRAM_adress_variable & (1<<1))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN5_LCD |= (help_var<<REG_NR_DATAPIN5_LCD);
	(CGRAM_adress_variable & (1<<0))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN4_LCD |= (help_var<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();
}

void set_DDRAM_address_LCD(unsigned char DDRAM_adress_variable)
{
	unsigned char help_var = 0;
	PORT_REG_RS_LCD &= ~(1<<REG_NR_RS_LCD);
	
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
	
	PORT_REG_DATAPIN7_LCD |= (1<<REG_NR_DATAPIN7_LCD);
	(DDRAM_adress_variable & (1<<6))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN6_LCD |= (help_var<<REG_NR_DATAPIN6_LCD);
	(DDRAM_adress_variable & (1<<5))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN5_LCD |= (help_var<<REG_NR_DATAPIN5_LCD);
	(DDRAM_adress_variable & (1<<4))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN4_LCD |= (help_var<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();
	
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
	
	(DDRAM_adress_variable & (1<<3))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN7_LCD |= (help_var<<REG_NR_DATAPIN7_LCD);
	(DDRAM_adress_variable & (1<<2))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN6_LCD |= (help_var<<REG_NR_DATAPIN6_LCD);
	(DDRAM_adress_variable & (1<<1))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN5_LCD |= (help_var<<REG_NR_DATAPIN5_LCD);
	(DDRAM_adress_variable & (1<<0))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN4_LCD |= (help_var<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();	
}

void write_data_to_LCD_as_byte(unsigned char data)
{
	unsigned char help_var = 0;
	PORT_REG_RS_LCD |= (1<<REG_NR_RS_LCD);
	
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
	
	(data & (1<<7))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN7_LCD |= (help_var<<REG_NR_DATAPIN7_LCD);
	(data & (1<<6))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN6_LCD |= (help_var<<REG_NR_DATAPIN6_LCD);
	(data & (1<<5))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN5_LCD |= (help_var<<REG_NR_DATAPIN5_LCD);
	(data & (1<<4))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN4_LCD |= (help_var<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();
	
	PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
	PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
	PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
	PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
	
	(data & (1<<3))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN7_LCD |= (help_var<<REG_NR_DATAPIN7_LCD);
	(data & (1<<2))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN6_LCD |= (help_var<<REG_NR_DATAPIN6_LCD);
	(data & (1<<1))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN5_LCD |= (help_var<<REG_NR_DATAPIN5_LCD);
	(data & (1<<0))?(help_var = 1):(help_var = 0);
	PORT_REG_DATAPIN4_LCD |= (help_var<<REG_NR_DATAPIN4_LCD);
	enable_LCD_4bit_library_function();
}

void write_data_to_LCD_as_string(char* string_pointer)
{
	unsigned char help_var = 0;
	PORT_REG_RS_LCD |= (1<<REG_NR_RS_LCD);
	
	for (; *string_pointer != '\0'; string_pointer++)
	{
		PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
		PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
		PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
		PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
			
		(*string_pointer & (1<<7))?(help_var = 1):(help_var = 0);
		PORT_REG_DATAPIN7_LCD |= (help_var<<REG_NR_DATAPIN7_LCD);
		(*string_pointer & (1<<6))?(help_var = 1):(help_var = 0);
		PORT_REG_DATAPIN6_LCD |= (help_var<<REG_NR_DATAPIN6_LCD);
		(*string_pointer & (1<<5))?(help_var = 1):(help_var = 0);
		PORT_REG_DATAPIN5_LCD |= (help_var<<REG_NR_DATAPIN5_LCD);
		(*string_pointer & (1<<4))?(help_var = 1):(help_var = 0);
		PORT_REG_DATAPIN4_LCD |= (help_var<<REG_NR_DATAPIN4_LCD);
		enable_LCD_4bit_library_function();
			
		PORT_REG_DATAPIN7_LCD &= ~(1<<REG_NR_DATAPIN7_LCD);
		PORT_REG_DATAPIN6_LCD &= ~(1<<REG_NR_DATAPIN6_LCD);
		PORT_REG_DATAPIN5_LCD &= ~(1<<REG_NR_DATAPIN5_LCD);
		PORT_REG_DATAPIN4_LCD &= ~(1<<REG_NR_DATAPIN4_LCD);
			
		(*string_pointer & (1<<3))?(help_var = 1):(help_var = 0);
		PORT_REG_DATAPIN7_LCD |= (help_var<<REG_NR_DATAPIN7_LCD);
		(*string_pointer & (1<<2))?(help_var = 1):(help_var = 0);
		PORT_REG_DATAPIN6_LCD |= (help_var<<REG_NR_DATAPIN6_LCD);
		(*string_pointer & (1<<1))?(help_var = 1):(help_var = 0);
		PORT_REG_DATAPIN5_LCD |= (help_var<<REG_NR_DATAPIN5_LCD);
		(*string_pointer & (1<<0))?(help_var = 1):(help_var = 0);
		PORT_REG_DATAPIN4_LCD |= (help_var<<REG_NR_DATAPIN4_LCD);
		enable_LCD_4bit_library_function();
	}
}
#endif