Close

We Get Signal

A project log for CircuitPython Badge

A handheld running CircuitPython and cheap enough for a badge.

dehipudeʃhipu 03/25/2018 at 20:250 Comments

While the PCB is ordered (thank you again @oshpark!), I decided that I can actually prototype using a Feather M0 and a prototyping shield that I made specially for this kind of tasks. I had to remove the header I already soldered to the LCD module, and since I was afraid to use hot air so close to the display, I had to do it the old-fashioned, rough way, and in the process stripped two of the pads. Fortunately they are find on the other side, which is also where they are connected, so everything still works. When the PCB comes, I will remove the display from that module anyways.

This is the display filled all black, without the backlight.

I quickly wrote a simple driver library for CircuitPython for handling the display. It uses almost the same commands as all the OLEDs out there. I didn't provide a "pixel" method, since you will be blitting whole bitmaps on it anyways.

class Display:
    _byte = bytearray(1)
    _word = bytearray(2)
    width = 128
    height = 64

    def __init__(self, spi, dc):
        self._spi = spi
        self._dc = dc
        pages = self.height // 8
        self.buffer = bytearray(self.width * pages)
        self._view = memoryview(self.buffer)
        self._move = bytearray(b'\xb0\x04\x10')
        self.reset()
        self.mirror(0)
        self.active(1)

    def _command(self, data):
        self._dc.value = 0
        self._spi.write(data)

    def reset(self):
        self._command(b'\xe2\x2f')

    def active(self, val):
        self._command(b'\xaf' if val else b'\xae')

    def inverse(self, val):
        self._command(b'\xa7' if val else b'\xa6')

    def vscroll(self, dy):
        self._byte[0] = 0x40 | dy & 0x3f
        self._command(self._byte)

    def flip(self, val):
        self._command(b'\xc0' if val else b'\xc8')

    def mirror(self, val):
        self._command(b'\xa0' if val else b'\xa1')
        self._move[1] = 0 if val else 4

    def contrast(self, val):
        self._word[0] = 0x81
        self._word[1] = val & 0xff
        self._command(self._word)

    def update(self):
        index = 0
        for page in range(self.height // 8):
            self._move[0] = 0xb0 | page
            self.value = 0
            self._spi.write(self._move)
            self._dc.value = 1
            self._spi.write(self._view[index:index + self.width])
            index += self.width

Next, I need an image class and a code for doing the blits with a mask. I might do the same optimization as I did for the #Micro:Boy and keep track of what parts of the display pages need updating — but at 40MHz SPI I don't really think it will be necessary.

Discussions