//****************************************************************************
// DRIVER I2C PARA LCD 20x4
// Modificado por Daniel Salgado
// Version: 1.0
// 22/11/2015
//****************************************************************************
//
// PCF8574P LCD
// ======== ======
// P0 RS
// P1 RW
// P2 Enable
// P3 Led Backlight
// P4 D4
// P5 D5
// P6 D6
// P7 D7
//
//
//****************************************************************************
#define LCD_ADDRS 0x40 //Direccion del PCF8574 o MUDULO
//Configuracion Pines de Control, datos de P4 a P7
#define LCD_RS 0x00// 4
#define LCD_RW 0x01// 5
#define LCD_E 0x02 // 6
#define LCD_BKLT 0x03 // 7 //BACKLIGHT
#define lcd_total_rows 4 //Number of rows: 1,2,3 or 4
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
//#define lcd_line_two 0x40 // LCD RAM address for the 2nd line
#define lcd_line_one 0x80 // LCD RAM address for line 1
#define lcd_line_two 0xC0 // LCD RAM address for line 2
#define lcd_line_three 0x94 // LCD RAM address for line 3
#define lcd_line_four 0xD4 // LCD RAM address for line 4
int8 const LCD_INIT_STRING[4] =
{
0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
0xc, // Enciende Display
1, // Borra Display
6 // Increment cursor
};
int1 i2c_envia(char addr,char data)
{
int1 ack;
i2c_start();
ack=i2c_write(addr);
if (ack!=0)
return FALSE;
i2c_write(data);
i2c_stop();
return TRUE;
}//FIN i2c_envia
int1 byte_to_PC8574(int8 chr)
{
return i2c_envia(LCD_ADDRS,chr); //Envia los datos al PC8574
}
//Macro to set a bit to a value
#define BIT_VAL(val,x,y) if(y) bit_set(val,x);else bit_clear(val,x)
int1 backlight=TRUE; //setea TRUE/FALSE Para habilitar el backlight
int1 regsel=FALSE;
int8 new_row_request=1;
//-------------------------------------
int1 lcd_send_nibble(int8 nibble)
{
int8 dummy=0;
swap(nibble); //Si utiliza como datos los 4 primeros pines
//borrar esta linea
dummy=nibble & 0xF0; //change to BIT_VAL functions if mapping is
//not D0 to D3 es 0xf. o D4 a D7 si 0xF0
//set the required bits in the output byte
#ifdef LCD_BKLT
BIT_VAL(dummy,LCD_BKLT,backlight); //sete el backlight a activo
#endif
BIT_VAL(dummy,LCD_RS,regsel); //add register select
//since dummy is initilised to 0, E always starts low.
if (!byte_to_PC8574(dummy))
return FALSE;
bit_set(dummy,LCD_E);
byte_to_PC8574(dummy); //Enable high
delay_ms(2);
bit_clear(dummy,LCD_E);
byte_to_PC8574(dummy); //and back low
//send the nibble, and pulse the enable.
return TRUE;
}
//----------------------------------------
// Send a byte to the LCD.
int1 lcd_send_byte(int8 address, int8 n)
{
if(address)
regsel=TRUE;
else
regsel=FALSE;
if (!lcd_send_nibble(n >> 4))
return FALSE;
lcd_send_nibble(n & 0xf);
return TRUE;
}
//----------------------------
int1 lcd_init(void)
{
int8 i;
// regsel=FALSE; //ensure starts with RS low
//Setup the I2C
delay_ms(15);
for(i=0 ;i < 3; i++)
{
if (!lcd_send_nibble(0x03))
return FALSE;
delay_ms(5);
}
lcd_send_nibble(0x02);
for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING[i]);
delay_ms(5);
}
return TRUE;
}
//----------------------------
void lcd_gotoxy(int8 x, int8 y)
{
int8 address;
switch(y)
{
case 1: address= lcd_line_one; break;
case 2: address= lcd_line_two; break;
case 3: address= lcd_line_three; break;
case 4: address= lcd_line_four; break;
default: address= 0; break;
}
address += x-1;
lcd_send_byte(0, 0x80 | address);
}
//-----------------------------
void lcd_putc(char c)
{
if(c=='ñ')
c=0xEE;
if(c=='°')
c=0xDF;
switch(c)
{
case '\a' : lcd_gotoxy(1,1); break;
case '\f':
lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n':
new_row_request++;
if (new_row_request>lcd_total_rows) new_row_request=1;
lcd_gotoxy(1, new_row_request);
break;
case '\b':
lcd_send_byte(0,0x10);
break;
default:
lcd_send_byte(1,c); delay_ms(5);
break;
}//FIN Switch
} //FIN lcd_putC