GfxLCD tests and fixes – area drawing

We have tests for page drawing algorithm. We can move on and add tests for area one. Writing tests for area drawing is much harder. This mode works on the device directly.
We need to create a dummy driver and chip class in such way that it would translate device’s command to an array.

Our Null driver needs to emulate a real device. But what exactly?
It appears that we need to simulate area operations and writing a colour. Not much.

from gfxlcd.abstract.driver import Driver


class AreaDriver(Driver):
    """Null communication driver"""
    def __init__(self, width, height):
        self.height = height
        self.width = width
        self.buffer = [[0] * self.height for x in range(self.width)]
        self.area = {
            'start_x': 0,
            'start_y': 0,
            'end_x': width,
            'end_y': height
        }
        self.pointer = (0, 0)

Our driver has a buffer to store what should be displayed. And area variable to keep track of selected area.
And finally, we have a pointer that shows where is our position in the area. This position is autoincremented after write.

    def init(self):
        """initialize pins"""
        pass

    def reset(self):
        """reset a display"""
        pass

    def cmd(self, data, enable):
        """send command to display"""
        pass

    def data(self, data, enable):
        """send data to display"""
        app_x, app_y = self.pointer
        self.buffer[self.area['start_x'] + app_x][self.area['start_y'] + app_y] = data
        self._inc_pointer()

When we send data to a device it must be a colour so in our dummy driver we add colour to buffer.

    def _inc_pointer(self):
        app_x, app_y = self.pointer
        app_x += 1
        if self.area['start_x'] + app_x > self.area['end_x']:
            app_x = 0
            app_y += 1

        if self.area['start_y'] + app_y > self.area['end_y']:
            app_x = 0
            app_y = 0

        self.pointer = (app_x, app_y)

This code keeps track of pointer and simulates area behaviour.

We have a driver that can be used in chip class:

from gfxlcd.drawing.area import Area
from gfxlcd.abstract.chip import Chip


class NullArea(Area, Chip):
    """Test chip driver for area drawing"""
    def __init__(self, width, height, driver, auto_flush=True):
        Chip.__init__(self, width, height, driver, auto_flush)
        Area.__init__(self, driver)
        self.rotation = 0

    def _converted_background_color(self):
        """dummy background color"""
        return 2

    def _converted_color(self):
        """dummy color"""
        return 1

In dummy, we can work on two colours 🙂

    def init(self):
        """init display"""
        self.driver.init()
        Area.init(self)
        Chip.init(self)
        self.driver.reset()

    def _set_area(self, pos_x1, pos_y1, pos_x2, pos_y2):
        """set area to work on"""
        self.driver.area = {
            'start_x': pos_x1,
            'start_y': pos_y1,
            'end_x': pos_x2,
            'end_y': pos_y2
        }
        self.driver.pointer = (0, 0)

We simulate calling set_area on a chip by setting area on dummy driver.
Hopefully, the driver can simulate real device in a good way :).

We can start our tests. First a pixel, circle and arc drawing. They are green.
Next our favourite drawing line and fail 🙂
A horizontal line is too short. Seems they are the same bugs like in page drawing.
We can safely copy changes like +1 to a range and divide with a floor. Also, we need to copy step calculation algorithm.
After this horizontal and vertical lines are green. What about the diagonal line?
Good:) We are green!
Automatically drawing and filling rectangle works also 🙂

We have tests now! Hurray. And of course, quick refactor. Move common line drawing functions to Pixel class. With tests, this is a breeze.

Summary

We fixed and paid some of the technological debt. With the test, it is always easier to develop software and refactor it.

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