I²C LCM1602 LCD screen

https://wiki.keyestudio.com/Ks0061_keyestudio_1602_I2C_Module

front

back

LCM1602: the LCD screen itself, not much to except it uses an Hitachi HD44780U controller: black spot at the back of the board.

Hitachi HD44780U: LCD controller (black spots at the back of the screen) with embedded font, in charge of controlling each pixel directly, reading character, cursor movement, and light control commands.

NXP PCF8574T: the chip in charge of multiplexing the signal of each pin into I²C, soldered at the 11 pins of the LCD screen:

I²C encapsulation

Communicating with the screen is a matter of talking to HD44780U through I²C encapsulation by HD44780U:

Wiring of HD44780U and PCF8574T

By testing the resistance between each pin of the PCF8574T and HD44780U, we observe this wiring between the two chips:

I²C Bit7 -> PCF8574T Port7 +-+ D7 HD44780U
I²C Bit6 -> PCF8574T Port6 +-+ D6 HD44780U
I²C Bit5 -> PCF8574T Port5 +-+ D5 HD44780U
I²C Bit4 -> PCF8574T Port4 +-+ D4 HD44780U
I²C Bit3 -> PCF8574T Port3 +--    HD44780U
I²C Bit2 -> PCF8574T Port2 +-+ E  HD44780U
I²C Bit1 -> PCF8574T Port1 +-+ RW HD44780U
I²C Bit0 -> PCF8574T Port0 +-+ RS HD44780U

Only D7 up and everything else down is given by this byte over I²C: 0b1000000.

HD44780U protocol

D0-D3: Not used as we do not have enough pins.

D4-D7: data port that send the ascii data or configuration bit patterns. As there are only 4 pins connected, the upper half is to be transmitted in a first transmission, and

E: The clock signal for the HD44780U to actually take the data in. Unlike I²C that uses a clock signal high to indicate that the data is stable, this device uses the edge from high to low to indicte the moment where to read the data from the pins. This can be emulated by first writing an I²C packet where E is high, then another where it is low.

RW: Register telling whether we read or write to the chip.

RS: Register that selects between the data or configuration space for the read/write operations.

Putting it all together

Building on top of an existing I²C library, we need:

send4bits(bits, flags) that writes 2 I1C packets with the same content: 4 bits with data ORed with E flag high on first packet, then low on second packet, to trigger the clock signal (high-low), then wait two ms.

send8bits(byte, flags) that calls send4bits() once with the high 4 bits of byte, once with the 4 low bits of byte.

The send4bits() can be called directly for initializing the 4-bit mode, and then send8bits() can be called for controlling the display or sending characters.