Using HD44780 on Raspberry Pi – part 6: 40×4 (buffered mode)

Last time we added support for lcd 40×4 by GPIO in direct mode. This time we will add buffered mode.

Download source

Older parts

Buffered mode

This should be quick and easy because we have only one function that send something to lcd, this function is flush().

Lets start from demo script. Open demos/ and add new function:

def test_1():
    drv = Gpio()
    drv.pins['E2'] = 10
    drv.pins['E'] = 24
    lcd_1 = lcd.CharLCD(40, 4, drv, 0, 0)
    lcd_1.write('-  Blarg !')
    lcd_1.write('-   Grarg !', 0, 1)
    lcd_1.write('-    ALIVE  !!!!', 0, 2)

    lcd_1.write('/* ', 19, 0)
    lcd_1.write('|*|', 19, 1)
    lcd_1.write(' */', 19, 2)


When you run it, lcd will show some weird content. Its again problem with addresses.

First lets move _get_enable from to Next change it a little by adding parameter pos_y=None to function. Next if pos_y is None set it as default position. Now we may pass line that interest us or just get current one.

Similar change to get_line_address, parameter pos_y set as default None and if none set to current.

We will end with such functions:

    def get_line_address(self, pos_y=None):
        """Return start hex address for line
            pos_y: line number
        if pos_y is None:
            pos_y = self.current_pos['y']

        if pos_y >= self.height or pos_y < 0:
            raise IndexError

        if not self.is_twin() or pos_y < 2: return LCD_LINES[pos_y] return LCD_LINES[pos_y - 2] def _get_enable(self, pos_y=None): """get proper enable line Args: pos_y: line number """ if pos_y is None: pos_y = self.current_pos['y'] if self.is_twin() and pos_y > 1:
            enable = 1
            enable = 0

        return enable

We are ready to change flush function in We need to modify calls to cmd and char as we done in direct mode. New function:

    def flush(self):
        """Flush buffer to screen, skips chars that didn't change"""
        if not self.dirty:
        bag = zip(range(0, self.get_height()), self.buffer, self.screen)
        for line, line_new, line_current in bag:
            if line_new != line_current:
                i = 0
                last_i = -1
                for char_new, char_current in zip(line_new, line_current):
                    if char_new != char_current:
                        if last_i != i:
                                self.get_line_address(line) + i,
                            last_i = i
                        last_i += 1
                    i += 1
                self.screen[line] = line_new
        self.dirty = False

After all that when you run demo code it should work properly.

Virtual buffered mode

Quick check on virtual correctness, open demos/ and ad new demo:

def main_test6():
    """test 3 - lcd 40x4 -> 20x4 + 20x4"""
    drv = Gpio()
    drv.pins['E2'] = 10
    drv.pins['E'] = 24
    lcd_1 = lcd.CharLCD(40, 4, drv, 0, 0)
    vlcd_1 = vlcd.CharLCD(20, 4)
    vlcd_1.add_display(0, 0, lcd_1)

    vlcd_2 = vlcd.CharLCD(20, 4)
    vlcd_2.add_display(0, 0, lcd_1, 20)


    vlcd_1.write('-First blarg1 !')
    vlcd_1.write('-Second blarg2 !', 0, 1)
    vlcd_1.write('-Third blarg3 !', 0, 2)
    vlcd_1.write('-Fourth blarg4 !', 0, 3)


    vlcd_2.write('-First blarg1 !')
    vlcd_2.write('-Second blarg2 !', 0, 1)
    vlcd_2.write('-Third blarg3 !', 0, 2)
    vlcd_2.write('-Fourth blarg4 !', 0, 3)


Run it and… all works as it should 🙂

Stop! Jenkins time!

And once again Jenkins automated tests. This time not much to fix.


We have added buffered mode for lcd with size 40×4.

Download source
Older parts


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s