HD44780
Display that is used is HD44780 with I2C IO-expander connected to it. This was an practical way to reduce used IO’s since otherwise minimun of 7-IO’s would be required by display(4-data,EN,RW,RS). Using expander, only two I2C-pins is used. Expander have been bought at ebay many years ago but aliexpress sells same thing still. I2C-expander chip is PCF8574.
memset function is used to init lcdbuf array to show clear on LCD. Otherwise first four init dataset is used for just in case, since some LCD-screen variations seems to require it. Rest of inits are done like HD44780 datasheet tells. Only reason why LCD is set to use 4-bit data is since this is ported to this platform from my old Atmel Atmega128 microcontroller code where 4-bit bus was used.
void lcdinit(){
memset((void*)&lcdbuf, 20, sizeof(int)*32); //alustetaan lcdbufferi näyttämään tyhjää
volatile unsigned char lcd_data;
lcd_data=0b00110000;
i2c_write_byte_no_reg(DEV_ADDR,lcd_data);
e_puls(lcd_data);
nrf_delay_ms(6);
lcd_data=0b00110000;
i2c_write_byte_no_reg(DEV_ADDR,lcd_data);
e_puls(lcd_data);
nrf_delay_ms(6);
lcd_data=0b00110000;
i2c_write_byte_no_reg(DEV_ADDR,lcd_data);
e_puls(lcd_data);
nrf_delay_ms(6);
lcd_data=0b00100000;
i2c_write_byte_no_reg(DEV_ADDR,lcd_data);
e_puls(lcd_data);
nrf_delay_ms(6);
sendcmd(0x28); nrf_delay_ms(2); //Function set, 4bit, 2rivinen, 42 us :0b00101000
sendcmd(0x08); nrf_delay_ms(2); //display off,curs off, blink off, 42 us:0b00001000
sendcmd(0x01); nrf_delay_ms(2); //clear display, min 1.64 ms :0b00000001
sendcmd(0x06); nrf_delay_ms(2); //entry mode set :0b00000110
sendcmd(0x0C); nrf_delay_ms(2); //display on,curs off,blink off :0b00001011
sendcmd(0x80); nrf_delay_ms(2); //DD-address=0 :0b10000000
sendcmd(2); nrf_delay_ms(2);
}
Since data is 4-bit, data send operation is done two times where first four high bits are send first, then lower four. This version of fuction is used to send commands, so RS bit is set to 0.
void sendcmd(volatile unsigned char a)
{
volatile unsigned char lcd_data=0;
lcd_data = (0b11110000 & a); //get high 4 bits
i2c_write_byte_no_reg(DEV_ADDR,lcd_data);
e_puls(lcd_data); //pulse to set D4-D7 bits
lcd_data = a<<4; //get low 4 bits
lcd_data =(lcd_data & 0b11110000);
i2c_write_byte_no_reg(DEV_ADDR,lcd_data);
e_puls(lcd_data);
}
This is same as previous, but RS bit is set to 1, signaling to LCD that character is send.
void sendchar(volatile unsigned char a)
{
volatile unsigned char lcd_data=0;
lcd_data = (0b11110000 & a)+1; //get high 4 bits
//RS 1-tilaan
i2c_write_byte_no_reg(DEV_ADDR,lcd_data);
e_puls(lcd_data); //pulse to set D4-D7 bits
lcd_data = a<<4; //get low 4 bits
lcd_data=(0b11110000 & lcd_data)+1;
i2c_write_byte_no_reg(DEV_ADDR,lcd_data);
e_puls(lcd_data);
}
This function is called whenever character on LCD is changed. Basically every character from buffer is send always when this function is called.
void lcdkirj()
{
int a;
sendcmd(128); nrf_delay_ms(2);
sendcmd(2); nrf_delay_ms(2);
for(a=0;a<=31;a++)
{
sendchar(lcdbuf[a]); nrf_delay_us(40);
if(a==15){ sendcmd(0b11000000); nrf_delay_us(40);}
}
}