Onion Omegaに小型液晶をつないでみた

[FreeBSDが動いているOnion Omega](https://qiita.com/yamori813/items/db62736cb88bcee9882d)に[Aitendoで購入した小型液晶](http://qiita.com/yamori813/items/ce2b6e79e079ec834e7e#t18spi-2p)を接続してmrubyで表示を試してみました。

液晶のコントローラーはSitronixのST7735Bで128x160の表示ができます。

LinuxとラズパイとPythonで試されているこちらの[ページ](https://raspberrylife.wordpress.com/2013/12/02/color-lcd/)を参考にさせてもらいました。

接続は以下のように行っています。

![Onion-TFT.png](https://qiita-image-store.s3.amazonaws.com/0/104066/df318c6c-04c4-c8cf-26d1-f62b11a30319.png)


SPI接続なのですが、ResetとRSというデータの種別を指定する信号が別に必要でこれらはGPIOで制御します。またSPIのデータ読み込みのためのMISOは接続されていません。

FreeBSDでユーザランドからSPIをコントロールするためのドライバspigenをmrubyから制御するために[mruby-bsdspi](https://github.com/yamori813/mruby-bsdspi)というgemを作ってみました。

![spigen.png](https://qiita-image-store.s3.amazonaws.com/0/104066/8b86f181-dc9a-f717-056d-e4cd1790e149.png)

以下をbuild_config.rbに追加してmrubyをビルドします。

```ruby
   conf.gem :git => 'https://github.com/yamori813/mruby-bsdgpio.git'
   conf.gem :git => 'https://github.com/yamori813/mruby-bsdspi.git'  
```

```ruby
#
# Original is this
# https://raspberrylife.wordpress.com/category/spi/
#

class ST7735
  RESET = 0
  RS = 8

  def initialize()
    @gpio = BsdGpio.new(0)
    @spi = BsdSpi.new(0)

    @gpio.setflags(RESET, BsdGpio::OUTPUT)  # reset
    @gpio.setflags(RS, BsdGpio::OUTPUT)  # RS
    @gpio.set(RESET, 1)
    reset()
    usleep(100)
    write_cmd([0x11])
    usleep(100)
    write([0xB1], [0x01, 0x2C, 0x2D])
    write([0xB2], [0x01, 0x2C, 0x2D])
    write([0xB3], [0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D])
    write([0xB4], [0x07])
    write([0xC0], [0xA2, 0x02, 0x84])
    write([0xC1], [0xC5])
    write([0xC2], [0x0A, 0x00])
    write([0xC3], [0x8A, 0x2A])
    write([0xC4], [0x8A, 0xEE])
    write([0xC5], [0x0E])
    write([0x36], [0xC8])
    write([0xE0], [0x02, 0x1C, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2D, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10])
    write([0xE1], [0x03, 0x1D, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10])
    write([0x2A], [0x00, 0x02, 0x00, 0x81])
    write([0x2B], [0x00, 0x01, 0x00, 0xA0])
    write([0x3A], [0x05])
    write_cmd([0x29])
  end

  def reset()
    @gpio.set(RESET, 0)
    usleep(100)
    @gpio.set(RESET, 1)
    usleep(100)
  end

  def write_cmd(a)
    @gpio.set(RS, 0)
    @spi.transfer(a, 0)
  end

  def write_data(a)
    @gpio.set(RS, 1)
    @spi.transfer(a, 0)
  end

  def write(c, d)
    write_cmd(c)
    write_data(d)
  end

  def write_rgb(r, g, b)
    write_data([r & 0xF8 | g >> 5, g & 0xFC << 3 | b >> 3])
  end

  def fill(r, g, b)
    write([0x2A], [0x00, 0x02, 0x00, 0x81])
    write([0x2B], [0x00, 0x01, 0x00, 0xA0])
    write_cmd([0x2C])
    for i in 1..160 do
      for n in 1..128 do
        write_rgb(r, g, b)
      end
    end
  end
end

lcd = ST7735.new()

lcd.write_cmd([0x2C])
lcd.fill(0, 0, 0)

for i in 1..160 do
  for n in 1..128 do
    if i < 22 then
      lcd.write_rgb(0xFF, 0xFF, 0xFF) # White
    elsif i < 44 then
      lcd.write_rgb(0xFF, 0xFF, 0x00) # Yellow
    elsif i < 66 then
      lcd.write_rgb(0x00, 0xFF, 0xFF) # Cyan
    elsif i < 88 then
      lcd.write_rgb(0x00, 0xFF, 0x00) # Green
    elsif i < 110 then
      lcd.write_rgb(0xFF, 0x00, 0xFF) # Magenta
    elsif i < 132 then
      lcd.write_rgb(0xFF, 0x00, 0x00) # Red
    else
      lcd.write_rgb(0x00, 0x00, 0xFF) # Blue
    end
  end
end
```

![IMGP0555.JPG](https://qiita-image-store.s3.amazonaws.com/0/104066/fa7cd9f6-9418-f717-76f5-8068ec0cff9b.jpeg)

今のところ画面全体の表示に5分くらいかかってしまい、実用になりません。。。oz_

追記：gpiospiのwaitをなくして、1K単位でのブロック転送にしたところ3秒くらいで表示できるようになりました。

追記：ユニバーサル基板を切って、シールドっぽくしてみました。

![写真（2018-02-27 14.33）.jpg](https://qiita-image-store.s3.amazonaws.com/0/104066/fefb5482-2ecb-304e-2093-69728e25fd84.jpeg)