/*
 * BP_LCD.h
 *
 *  Created on: 30. 10. 2016
 *      Author:
 */

#ifndef BP_LCD_H_
#define BP_LCD_H_

#include <avr/io.h>
#include <util/delay.h>

static void LCD_Enable_impulse(void);
static void LCD_wait_while_busy(void);
static void LCD_send_a_char(unsigned char c);
static void LCD_send_a_command(unsigned char c);
void LCD_init(void);
void LCD_send_a_string(char *c);
void LCD_change_cursor_pos(unsigned char Pos, unsigned char Line);
void LCD_clear_and_home(void);
void LCD_string_effect(char *Str);

static void LCD_Enable_impulse() {
	_delay_us(10);
	LCD_Control |= (1<<LCD_Enable);
	_delay_us(10);
	LCD_Control &= ~(1<<LCD_Enable);
}

void LCD_init() {
	LCD_Control_Data_Dir |= (1<<LCD_Enable) | (1<<LCD_ReadWrite) | (1<<LCD_RS); //Set as output pins
	LCD_Control &= ~((1<<LCD_Enable) | (1<<LCD_ReadWrite) | (1<<LCD_RS));  //Clear control bits
	_delay_ms(100);			// Wait 100 ms
	LCD_Data_Dir = 0xFF;	//Set Data port to output

	LCD_Data = 0x01;		//Clear Screen 0x01
	LCD_Enable_impulse();
	_delay_ms(2);

	LCD_Data = 0x38;		//Function Set 0b00111000    DL=1(8bit),N=1(1/16duty),F=0(5x7dots)
	LCD_Enable_impulse();
	_delay_us(50);

	LCD_Data = 0b00001100;	//Display ON/OFF  D=1(Disp on),C=0(Cursor off),B=0(Blink off)
	LCD_Enable_impulse();
	_delay_us(50);

	LCD_Data = 0b00000110;	//Entry mod set   I/D=1(increment),S=0(No shift)
	LCD_Enable_impulse();
	_delay_us(50);

	LCD_Data = 0b00000010;	//Cursor at home 0x02
	LCD_Enable_impulse();
	_delay_ms(2);
}

static void LCD_wait_while_busy() {
	LCD_Data_Dir = 0x00;				//Set Data port to input
	LCD_Control |= 1<<LCD_ReadWrite; 	//Set ReadWrite to 1 (Write)
	LCD_Control &= ~1<<LCD_RS;			//Clear RS
	LCD_Enable_impulse();				//Send 1 impulse to Enable
	while (LCD_Data >= 0x80)			//If busy, wait 5 us and ask again (MSB on data is BF - busy flag)
	{
		_delay_us(5);
		LCD_Enable_impulse();
	}
	LCD_Data_Dir = 0xFF;	//Set Data port to output
}

static void LCD_send_a_char(unsigned char c) {
	LCD_wait_while_busy();
	LCD_Data = c;
	LCD_Control &= ~(1<<LCD_ReadWrite);	//Set ReadWrite to 0 (Read)
	LCD_Control |= 1<<LCD_RS;			//Set RS to 1
	LCD_Enable_impulse();				//Send 1 impulse to Enable
	LCD_Data = 0;						//Clear Data port
}

static void LCD_send_a_command(unsigned char c) {
	LCD_wait_while_busy();
	LCD_Data = c;
	LCD_Control &= ~((1<<LCD_ReadWrite) | (1<<LCD_RS));	//Clear ReadWrite (Read) and RS
	LCD_Enable_impulse();				//Send 1 impulse to Enable
	LCD_Data = 0;						//Clear Data port
}

void LCD_send_a_string(char *Str) {
	while (*Str != 0x0A) {				//Send a character on pointer position and increment point,
		LCD_send_a_char(*Str++);		//until character is 0x0A
	}

}

void LCD_change_cursor_pos(unsigned char Pos, unsigned char Line) {
	Pos |= 0x80;						//Set MSB to 1 to let LCD know, you're setting cursor
	if (Line > 0) Pos += 0x40;
	LCD_send_a_command(Pos);			//The rest is cursor position
}

void LCD_clear_and_home() {
	LCD_change_cursor_pos(0,0);
	LCD_send_a_string("                \n");
	LCD_change_cursor_pos(0,1);
	LCD_send_a_string("                \n");
	LCD_change_cursor_pos(0,0);
}

void LCD_string_effect(char *Str) {
	while (*Str >= 0x20) {	//Send a character on pointer position and increment point,
		LCD_send_a_char(*Str++);				//until character is 0x0A or 0x0D
		_delay_ms(100);
	}
}


#endif /* BP_LCD_H_ */

