Color LCD(4)

前回試してみたSPI接続カラーLCDへの画像ファイル表示。イメージ処理モジュールを利用して簡単に行う事ができたが、表示速度が思ったよりもかなり遅い。

これは1ピクセル単位でSPI通信を行っているため、オーバーヘッドが大きいのだろうと推測して、複数バイトをまとめて転送するように書き換えてみた。

spidevのxfer2は4096バイトまでまとめて転送できるようなので、画面の塗りつぶしは2048ピクセルの転送を10回、イメージの表示は128ピクセルの1ライン分を160回転送するようにした。プログラムは以下の通り。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import RPi.GPIO as GPIO
import spidev           # sudo pip install spidev
import time
import sys
from PIL import Image   # sudo pip install pillow

class ST7735:
    def __init__(self):
        self.spi = spidev.SpiDev()
        self.spi.open(0, 0)
        self.spi.max_speed_hz = 16000000
        GPIO.setmode(GPIO.BCM)
        GPIO.setwarnings(False)
        GPIO.setup(24, GPIO.OUT)
        GPIO.setup(25, GPIO.OUT)
        self.reset()
        self.write_cmd(0x11)
        time.sleep(0.12)
        self.write((0xB1, 0x01, 0x2C, 0x2D))
        self.write((0xB2, 0x01, 0x2C, 0x2D))
        self.write((0xB3, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D))
        self.write((0xB4, 0x07))
        self.write((0xC0, 0xA2, 0x02, 0x84))
        self.write((0xC1, 0xC5))
        self.write((0xC2, 0x0A, 0x00))
        self.write((0xC3, 0x8A, 0x2A))
        self.write((0xC4, 0x8A, 0xEE))
        self.write((0xC5, 0x0E))
        self.write((0x36, 0xC8))
        self.write((0xE0, 0x02, 0x1C, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2D, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10))
        self.write((0xE1, 0x03, 0x1D, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10))
        self.write((0x2A, 0x00, 0x02, 0x00, 0x81))
        self.write((0x2B, 0x00, 0x01, 0x00, 0xA0))
        self.write((0x3A, 0x05))
        self.write_cmd(0x29)
    def reset(self):
        GPIO.output(25, False)
        time.sleep(0.1)
        GPIO.output(25, True)
        time.sleep(0.1)
    def write_cmd(self, cmd):
        GPIO.output(24, False)  # RS=0
        self.spi.xfer2([cmd])
    def write_data(self, data):
        GPIO.output(24, True)   # RS=1
        self.spi.xfer2([data])
    def write(self, cmd):
        if len(cmd) == 0:
            return
        GPIO.output(24, False)  # RS=0
        self.spi.xfer2([cmd[0]])
        GPIO.output(24, True)   # RS=1
        self.spi.xfer2(list(cmd[1:]))
    def write_rgb(self, r, g, b):
        self.write_data(r & 0xF8 | g >> 5)
        self.write_data(g & 0xFC << 3 | b >> 3)
    def fill(self, r, g, b):
        self.write((0x2A, 0x00, 0x02, 0x00, 0x81))
        self.write((0x2B, 0x00, 0x01, 0x00, 0xA0))
        self.write_cmd(0x2C)
        GPIO.output(24, True)   # RS=1
        hi = r & 0xF8 | g >> 5
        lo = g & 0xFC << 3 | b >> 3
        pixline = []
        for n in range(2048):
            pixline.append(hi)        
            pixline.append(lo)
        for n in range(10):
            self.spi.xfer2(pixline[0:])
    def image(self, file):
        try:
            im = Image.open(file).convert("RGB")
            im.thumbnail((128, 160))
            pix = im.load()
            self.write((0x2A, 0x00, 0x02, 0x00, 0x81))
            self.write((0x2B, 0x00, 0x01, 0x00, 0xA0))
            self.write_cmd(0x2C)
            GPIO.output(24, True)   # RS=1
            pixline = []
            for i in range(160):
                for n in range(128):
                    pixel = pix[n, i]
                    hi = pixel[0] & 0xF8 | pixel[1] >> 5
                    lo = pixel[1] & 0xFC << 3 | pixel[2] >> 3
                    pixline.append(hi)
                    pixline.append(lo)
                self.spi.xfer2(pixline)
                del pixline[:]
        except:
            pass

if __name__ == "__main__":
    lcd = ST7735()
    param = sys.argv
    t1 = time.clock()
    for n in range(100):
        lcd.fill(0, 0, 0)
        lcd.image(param[1])
    t2 = time.clock()
    print 'processing time : ', str(t2 - t1)
    try:
        while True:
            pass
    except KeyboardInterrupt:
        print '\nbreak'
    GPIO.cleanup()

画面のクリアとイメージ表示を100回くり返すようにして、所要時間を旧バージョンと比べてみると、以下のようになった。

$ sudo python spilcd2.py Lenna.png
processing time :  36.28
$ sudo python spilcd.py Lenna.png
processing time :  283.74

結果は一目瞭然で、8倍近く高速化できた。
このぐらいの速度で表示できるのなら、Pythonだけでも何か実用性のある使い方ができるかも知れない。

コメントを残す