NodeMCU and HD44870 – part 3

Our module displays strings as soon as function write is called. It is mostly enough but sometimes it is better to prepare what we want to display and then display it. Such action uses buffer and that why I’m calling this buffered mode.
We made something like this in CharLCD so we can convert idea to NodeMCU. Due to LUA characteristic both modes are combined into one module.

What we want is to have one write function and its functionality depends on mode. It must do different operations for each mode.
Lets declare variable mode and set it to direct as default:

lcd_hd44870.mode = 'direct'

When we call lcd() we are in direct mode, so we will add another constructor buffered() for buffered mode.

lcd_hd44870.buffered = function(width, height, pins)    
    lcd_hd44870.lcd(width, height, pins)   
    lcd_hd44870.mode = 'buffered'
    lcd_hd44870.buffer = {}
    lcd_hd44870.screen = {}   
    for x=0, lcd_hd44870.width-1 do
        lcd_hd44870.buffer[x] = {}
        lcd_hd44870.screen[x] = {}
        for y=0, lcd_hd44870.height-1 do
            lcd_hd44870.buffer[x][y] = " "
            lcd_hd44870.screen[x][y] = " "
        end        
    end 
end

Write function detect what mode is active and calls _write_direct or _write_buffered.

lcd_hd44870.write = function(chars)
    if lcd_hd44870.mode == 'direct' then lcd_hd44870._write_direct(chars) end
    if lcd_hd44870.mode == 'buffered' then lcd_hd44870._write_buffered(chars) end
end

lcd_hd44870._write_direct = function(chars)
    gpio.write(lcd_hd44870.pins['RS'], gpio.HIGH)
    for i = 1, #chars do
        lcd_hd44870._write8(chars:byte(i))        
    end
    lcd_hd44870.x =  lcd_hd44870.x + #chars
end

Buffered type write chars to buffer:

lcd_hd44870._write_buffered = function(chars)    
    for i = 1, #chars do
        lcd_hd44870.buffer[lcd_hd44870.x + i - 1][lcd_hd44870.y] = chars:sub(i,i)
    end
    lcd_hd44870.x = lcd_hd44870.x + #chars
end

To display content on screen we call flush function. It uses few tricks, like it tries to find only those chars that need to be changed and it tries to use set_xy as little as possible.

lcd_hd44870.flush = function()    
    current_xy = lcd_hd44870.get_xy()

    last_x = -1
    last_y = -1
    for y=0, lcd_hd44870.height-1 do              
        for x=0, lcd_hd44870.width-1 do
            if lcd_hd44870.buffer[x][y] ~= lcd_hd44870.screen[x][y] then               
                if last_x + 1 ~= x or last_y ~=y then                   
                    lcd_hd44870.set_xy(x, y) 
                end
                last_x = x
                last_y = y               
                gpio.write(lcd_hd44870.pins['RS'], gpio.HIGH)                
                lcd_hd44870._write8(lcd_hd44870.buffer[x][y]:byte(1))
                lcd_hd44870.screen[x][y] = lcd_hd44870.buffer[x][y]
            end
        end
    end   

    lcd_hd44870.set_xy(current_xy['x'], current_xy['y'])
end

Some code was written it is good idea to check if it works. Open main.lua and paste:

lcd.buffered(16, 2)
lcd.init()
lcd.set_xy(0, 0)
lcd.write("The cat")
lcd.set_xy(0, 1)
lcd.write("and meows")

lcd.flush()
lcd.set_xy(10, 0)
lcd.write("purrs")

lcd.flush()

Everything works and my screen displayed something like this:

img_20161218_210333

Buffer clear

When our buffer become messy we should be able to clear it:

lcd_hd44870.clear = function() 
    if lcd_hd44870.mode == 'buffered' then
        for x=0, lcd_hd44870.width-1 do
            lcd_hd44870.buffer[x] = {}
            for y=0, lcd_hd44870.height-1 do
                lcd_hd44870.buffer[x][y] = " "
            end
        end 
    end        
end

Summary

We can now use lcd in two modes, direct where each char is displayed directly on screen, and buffered where buffer is prepared and then flushed to screen.
It is similar to what we have done in python.

It’s going quite nice. Time to see if adding drivers (GPIO and i2c) is hard 🙂

Want this module? Get it with bolierplate from here

 

Advertisements

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s