// s_lcd.c ----------------------------------

#define LCD_DB4   PIN_A0 
#define LCD_DB5   PIN_A1 
#define LCD_DB6   PIN_A2 
#define LCD_DB7   PIN_A3

#define LCD_E     PIN_A5 
#define LCD_RS    PIN_A4 
//#define LCD_RW    PIN_A2 
   
// If you only want a 6-pin interface to your LCD, then 
// connect the R/W pin on the LCD to ground, and comment 
// out the following line. 
//#define USE_LCD_RW   1  

// Saját parancsok 
#define CLR 1
#define HOME 2
#define LINE2_HOME 3
#define BLINK_ON 4
#define BLINK_OFF 5
#define LINE1_CLR 6
#define LINE2_CLR 7

#define LCD_CGRAM_BASE_ADDR 0x40 // Set the CGRAM address
int8 const LCD_CUSTOM_CHARS[56] = 
{
// saját ékezetes betűkészlet
	0x04,0x0E,0x15,0x11,0x11,0x11,0x0E,0x00, // 0 Ó  
	0x04,0x08,0x04,0x0A,0x11,0x1F,0x11,0x00, // 1 Á
	0x02,0x04,0x0E,0x01,0x0F,0x11,0x0F,0x00, // 2 á
	0x02,0x04,0x0E,0x11,0x1F,0x10,0x0E,0x00, // 3 é
	0x02,0x04,0x0E,0x11,0x11,0x11,0x0E,0x00, // 4 ó 
	0x02,0x04,0x1F,0x10,0x1E,0x10,0x1F,0x00, // 5 É 
	0x02,0x04,0x11,0x11,0x11,0x13,0x0D,0x00, // 6 ú
}; 
int8 const LCD_CUSTOM_CHARS1[8] = 
{
	0x09,0x12,0x00,0x0E,0x11,0x11,0x0E,0x00  // 7 ő
};					 
int8 const LCD_CUSTOM_CHARS2[8] = 
{
	0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00  // 7 fok jele
}; 
                                             // ö 239
                                             // ü 245
   
//======================================== 

#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines 
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line 

int8 const LCD_INIT_STRING[5] =
{ 
	0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots 
 	0x08
 	0xc,                    // Display on 
 	1,                      // Clear display 
 	6                       // Increment cursor 
}; 
//-------------------------------------

//------------------------------------- 
void lcd_send_nibble(int8 nibble)
{ 
// Note:  !! converts an integer expression 
// to a boolean (1 or 0). 
	output_bit(LCD_DB4, !!(nibble & 1)); 
 	output_bit(LCD_DB5, !!(nibble & 2));  
	output_bit(LCD_DB6, !!(nibble & 4));    
	output_bit(LCD_DB7, !!(nibble & 8));    

 	delay_cycles(2); 
 	output_high(LCD_E); 
 	delay_us(2); 
 	output_low(LCD_E); 
} 
//----------------------------------- 
// This sub-routine is only called by lcd_read_byte(). 
// It's not a stand-alone routine.  For example, the 
// R/W signal is set high by lcd_read_byte() before 
// this routine is called.      

#ifdef USE_LCD_RW 
	int8 lcd_read_nibble(void)
	{ 
		int8 retval; 
// Create bit variables so that we can easily set 
// individual bits in the retval variable. 
		#bit retval_0 = retval.0 
		#bit retval_1 = retval.1 
		#bit retval_2 = retval.2 
		#bit retval_3 = retval.3 

		retval = 0; 
    
		output_high(LCD_E); 
		delay_cycles(2); 

		retval_0 = input(LCD_DB4); 
		retval_1 = input(LCD_DB5); 
		retval_2 = input(LCD_DB6); 
		retval_3 = input(LCD_DB7); 
  
		output_low(LCD_E); 
    
		return(retval);    
	}    
#endif 
//--------------------------------------- 
// Read a byte from the LCD and return it. 

#ifdef USE_LCD_RW 
	int8 lcd_read_byte(void)
	{ 
		int8 low, high; 

		output_high(LCD_RW); 
		delay_cycles(2); 

		high = lcd_read_nibble(); 
		low = lcd_read_nibble(); 
		return( (high<<4) | low); 
	} 
#endif 
//---------------------------------------- 
// Send a byte to the LCD. 
void lcd_send_byte(int8 address, int8 n)
{ 
	output_low(LCD_RS); 

	#ifdef USE_LCD_RW 
		while(bit_test(lcd_read_byte(),7)) ; 
	#else 
		delay_us(60);  
	#endif 

	if (address) 
		output_high(LCD_RS); 
	else 
		output_low(LCD_RS); 
		delay_cycles(2); 
	
	#ifdef USE_LCD_RW 
		output_low(LCD_RW); 
		delay_cycles(2); 
	#endif 

	output_low(LCD_E); 
	lcd_send_nibble(n >> 4); 
	lcd_send_nibble(n & 0xf); 
} 
//---------------------------- 
void lcd_gotoxy(int8 x, int8 y)
{ 
	int8 address; 
	if(y != 1) 
   		address = lcd_line_two; 
	else 
   		address=0; 
		address += x-1; 
		lcd_send_byte(0, 0x80 | address); 
} 
//-----------------------------
void lcd_init_custom_chars(int8 j) 
{
	int8 i;
	switch(j)
	{
		case 0: 
			lcd_send_byte(0,LCD_CGRAM_BASE_ADDR);
			for (i=0;i<sizeof(LCD_CUSTOM_CHARS);i++) 
			{
				lcd_send_byte(1,LCD_CUSTOM_CHARS[i]);
				delay_ms(2);
			}
			break;
		case 1: 
			lcd_send_byte(0,LCD_CGRAM_BASE_ADDR+56);
			for (i=0;i<sizeof(LCD_CUSTOM_CHARS1);i++)
			{
				lcd_send_byte(1,LCD_CUSTOM_CHARS1[i]);
				delay_ms(2);
			}
			break;
		case 2:
			lcd_send_byte(0,LCD_CGRAM_BASE_ADDR+56);
			for (i=0;i<sizeof(LCD_CUSTOM_CHARS2);i++)
			{
				lcd_send_byte(1,LCD_CUSTOM_CHARS2[i]);
				delay_ms(2);
			}
			break;
	}
}
//----------------------------- 
/*void lcd_putc(char c)
{
	lcd_send_byte(1,c); 
}
*/
void lcd_putc( char c) 
{
	switch (c)
	{
    	case '\f'   : lcd_send_byte(0,1);
        	          delay_ms(2);			 break;
    	case '\n'   : lcd_gotoxy(1,2);       break;
    	case '\b'   : lcd_send_byte(0,0x10); break;
    	    												// ékezetes betűk
    	case 'Ó'	: lcd_send_byte(1,0);	 break;
    	case 'Á'	: lcd_send_byte(1,1);	 break;
    	case 'á'	: lcd_send_byte(1,2);	 break;	
     	case 'é'	: lcd_send_byte(1,3);	 break;
     	case 'ó'	: lcd_send_byte(1,4);	 break;
     	case 'É'	: lcd_send_byte(1,5);	 break;
     	case 'ú'	: lcd_send_byte(1,6);	 break;
     	case '°'	: lcd_send_byte(1,7);	 break;
     	case 'ö'	: lcd_send_byte(1,239);	 break;
     	case 'ü'	: lcd_send_byte(1,245);	 break;
     	
     	default     : lcd_send_byte(1,c);    break;
   	}
}

//------------------------------
void lcd_cmd(int8 i)	//Saját parancsok 
{
	switch(i)
	{
		case CLR:		lcd_send_byte(0,1); 
						delay_ms(2);			break;
		case HOME: 		lcd_send_byte(0,2);		break;
		case LINE2_HOME:lcd_gotoxy(2,1); 		break;
		case BLINK_ON: 	lcd_send_byte(0,0x0e);	break;	//kurzor villogtatás
		case BLINK_OFF: lcd_send_byte(0,0x0c);	break;
		case LINE1_CLR: lcd_gotoxy(1,1);
						lcd_putc("                ");break; 
		case LINE2_CLR:	lcd_gotoxy(2,1);
						lcd_putc("                ");break; 
	}
}
//------------------------------
void lcd_teszt()	//Oda-vissza futó csíkok az LCD-n
{
	int8 i,j,k;
	k=0xff;
	for(j=0;j<2;j++)
	{
		for(i=0x80;i<0x90;i++)
		{
			lcd_send_byte(0,i);
			lcd_send_byte(1,k);
			lcd_send_byte(0,i+0x40);
			lcd_send_byte(1,k);
			delay_ms(50);
		}
		k=0x20;
	}
	k=0xff;
	for(j=0;j<2;j++)
	{
		for(i=0x8f;i>=0x80;i--)
		{
			lcd_send_byte(0,i);
			lcd_send_byte(1,k);
			lcd_send_byte(0,i+0x40);
			lcd_send_byte(1,k);
			delay_ms(50);
		}
		k=0x20;
	}
}
//------------------------------ 
#ifdef USE_LCD_RW 
char lcd_getc(int8 x,int8 y) 
{ 
	char value; 

	lcd_gotoxy(x,y); 

	// Wait until busy flag is low. 
	while(bit_test(lcd_read_byte(),7));  
	output_high(LCD_RS); 
	value = lcd_read_byte(); 
	output_low(lcd_RS); 

	return(value); 
} 
#endif
//--------------------------------

void lcd_init(void)
{ 
	int8 i; 

	output_low(LCD_RS); 
	#ifdef USE_LCD_RW 
		output_low(LCD_RW); 
	#endif 

	output_low(LCD_E); 
	delay_ms(15); 
	for(i=0 ;i < 3; i++)
	{ 
    	lcd_send_nibble(0x03); 
    	delay_ms(5); 
   	} 
	lcd_send_nibble(0x02); 
	for(i=0; i < sizeof(LCD_INIT_STRING); i++)
	{ 
    	lcd_send_byte(0, LCD_INIT_STRING[i]); 
    // If the R/W signal is not used, then 
    // the busy bit can't be polled.  One of 
    // the init commands takes longer than 
    // the hard-coded delay of 60 us, so in 
    // that case, lets just do a 5 ms delay 
    // after all four of them. 
    	#ifndef USE_LCD_RW 
    		delay_ms(5); 
    	#endif 
	} 
} 
//---------------------------- 