//************************************************* LCD portbillegető függvények ************************************************

//Ez a három függvény hardverspecifikus, függ a portok bekötésétől, a kontrollertől, és a bitmódtól.
//Ezeket használják a könyvtári függvények, ezért ki kell őket cserélni az adott hardverre írt függvényekkel
//Jelen változatban az adatbusz 8 bites, az LCD is 8 biten van programozva,
//és más periféria is használja ezt az adatbuszt. Emiatt el kell menteni/visszatölteni.
//Ha csak az LCD használja az adatbuszt, értelemszerűen ezek a függvények leegyszerűsíthetőek...




//impulzust ad ki az LCD Enable bemenetén - adat/parancs átírás
void lcd_toggle_E()
{
	_delay_us(30);
	LDEN_PORT |= lcd_enable;
	_delay_us(50);
	LDEN_PORT &= ~lcd_enable;
	_delay_us(30);
}

//adatot küld ki az LCD-re, pl. karaktereket vagy CGRAM adatot
//mivel a LED_PORT - ot használja az adatátvitelnél, az átírás idejére lekapcsolja és elmenti a LED-eket!
void lcd_data_write(byte data)
{
	byte ledportdata = LED_PORT;	//LED adatvonal elmentése
	byte ldenportdata= LDEN_PORT;	//LED engedélyező port elmentése...
	LDEN_PORT        = led_blank|lcd_datafunc;	//...majd lekapcsolása, és az adatbit bebillentése
	LED_PORT 		 = data;		//adat kirakása az adatvonalra
	_delay_us(50);					//tranziensidő (LED-port és adatvonal stabilizálódás);
	lcd_toggle_E();					//átírás impulzus
	LED_PORT         = ledportdata; //adatvonal visszatöltése
	LDEN_PORT        = ldenportdata;//engedélyező port visszatöltése
}

//parancsot küld az LCD-nek - konfigurálás, kurzorbeállítás, stb
//mivel a LED_PORT - ot használja az adatátvitelnél, az átírás idejére lekapcsolja és elmenti a LED-eket!
void lcd_command_write(byte command)
{
	byte ledportdata = LED_PORT;	//LED adatvonal elmentése
	byte ldenportdata= LDEN_PORT;	//LED engedélyező port elmentése...
	LDEN_PORT        = led_blank&(~lcd_datafunc);	//...majd lekapcsolása, és az adatbit törlése(parancs lesz!)
	LED_PORT 		 = command;		//parancs kirakása az adatvonalra
	_delay_us(50);					//tranziensidő (LED-port és adatvonal stabilizálódás);
	lcd_toggle_E();					//átírás impulzus
	LED_PORT         = ledportdata; //adatvonal visszatöltése
	LDEN_PORT        = ldenportdata;//engedélyező port visszatöltése
}



//************************************************* LCD könyvtári függvények ************************************************

//Ezek a függvények jelentik a HD44780 kompatíbilis LCD kijelző kezelőfüggvényeit.
//Más kontrollerre(pl. 8051), de akár PC-re is átvihető lényegi változtatás nélkül,
egyedül a három hardverspecifkus portkezelő  függvényt kell kicserélni.


//LCD bekapcsolás/inicializálás:
void lcd_init()
{
	//kijelző alaphelyzetbe állítás - 3-szor kiadva a biztonság érdekében:
	lcd_command_write(0b00000010); _delay_ms(5);
	lcd_command_write(0b00000010); _delay_ms(5);
	lcd_command_write(0b00000010); _delay_ms(5);
	//kijelző törlés:
	lcd_command_write(0b00000001); _delay_ms(5);
	//karakterbeviteli mód: inkrementális, íráskor jobbra haladás:
	lcd_command_write(0b00000110);
	//kijelző (meghajtás) bekapcsolása + kurzor bekapcsolás(aláhúz+villog):
	lcd_command_write(0b00001111);
	//kurzor eltolás beállítása - jobbra tol, képernyő fix:
	lcd_command_write(0b00010100);
	//funkció beállítás - 8-bites, 2 soros, 5×7 pixel mód:
	lcd_command_write(0b00111000);
	//karakterbeviteli mód - kurzor a bal felső sarokba:
	lcd_command_write(0b10000000);
}

//LCD kijelző (tartalmának) törlése:
void lcd_cls()
{
	lcd_command_write(0b00000001);
	_delay_ms(5);
}

//kurzor beállítás:
void lcd_kurzor(byte alahuzas, byte villogas)
{
	alahuzas &= 1;
	villogas &= 1;
	lcd_command_write(0b00001100 + (alahuzas<<1) + villogas);
}

void lcd_gotoXY(byte x, byte y)
{
	switch(y)
	{
		case 1:  x+=0x40; break;
		case 2:  x+=0x14; break;
		case 3:  x+=0x54; break;
		default: x+=0x00; //y=0
	}
	//LCD DDRAM address:
	lcd_command_write(0b10000000 + x);
}

// #0 - végű karakterláncot ír ki az LCD kijelzőre
//ékezetes karakterek nincsenek beépítve - lásd a kijelző adatlapját
void lcd_write(char* S)
{
	int i=0;
	while(S[i] && i<255)
	{
		lcd_data_write(S[i]);
		i++;
	}

}

//Nincs leprogramozva:
// - DDRAM cím közvetlen beállítása
// - CGRAM beállítás
// - egyéni karakterek pixelgrafikus bevitele(0-7 karakódokra) - lényegében adat írás CGRAM cím beállítás után
//Egyéni karakterek: Kiíratáskor használjuk a 8-15 kódokat(ekvivalensek a 0-7 kódokkal), mivel 0-végű sztringeket használunk!

//************************************************* LCD egyéni programok ************************************************

//példaprogram a könyvár használatára


void lcd_demo_kiir()
{
	lcd_hattervilagitas(1);
	lcd_init();
	lcd_kurzor(0,0);
	lcd_gotoXY(0,0);
	lcd_write("zombee lcd");

	int i=0;
	int j=0;
	int x=18;

	while(1)
	{
		j=i;
		x=18;
		while(j>0)
		{
			lcd_gotoXY(x,1);
			lcd_data_write((j % 10)+48);
			j=j/10;
			x--;
		}

		_delay_ms(1000);
		i++;

	}

	while(1);
}
