pcDuinoに激安液晶を接続してみた

後日追記：この液晶は壊れてしまいました。

pcDuinoのピンヘッダーはこんなになっていて、以前aitendoで購入した[激安液晶](https://qiita.com/yamori813/items/ce2b6e79e079ec834e7e#m028c9325tp)を接続してみました。

J11

|PIN|CON|NO|LCD|dts|変更|
|:--|:--|:--|:--|:--|:--|
|UART2_RX|PI19|172|D8|8 19|CS|
|UART2_TX|PI18|171|D9|8 18|RD|
|GPIO2|PH7|132|D10|7 7|D8|
|PWM0|PH6|131|D11|7 6|WR|
|GPIO3|PH8|133|D12|7 8|D9|
|PWM1|PB2|20|D13|1 2|RST|
|PWM2|PI3|156|D14|8 3|RS|
|GPIO4|PH9|134|D15|7 9|D10|

J8

|PIN|CON|NO|LCD|dts|変更|
|:--|:--|:--|:--|:--|:--|
|GPIO5|PH10|135|RST|7 10|D11|
|PWM3|PH5|130|||D_RQ|
|SPI0_CS|PI10|163|||D_CD|
|SPI0_MOSI|PI12|165|||D_IN|
|SPI0_MISO|PI13|166|||D_OUT|
|SPI0_CLK|PI11|164|||D_CLK|
|GND||||||
|ARef||||||
|TWI2-SDA|PB21|39||||
|TWI2-SCK|PB20|38||||

J11

|PIN|CON|NO|LCD|dts|変更|
|:--|:--|:--|:--|:--|:--|
|GPIO6|PH11|136|RS|7 11|D12|
|GPIO7|PH12|137|WR|7 12|D13|
|GPIO8|PH13|138|RD|7 13|D14|
|GPIO9|PH14|139|CS|7 14|D15|

mrubyで確認してみます。mruby-bsdgpioを使っています。

```ruby
#
# original is LCD_ID_readreg.ino
#

LCD_RST = 135
LCD_CS = 139
LCD_RS = 136
LCD_WR = 137
LCD_RD = 138

LCD_D8 = 172
LCD_D9 = 171
LCD_D10 = 132
LCD_D11 = 131
LCD_D12 = 133
LCD_D13 = 20
LCD_D14 = 156
LCD_D15 = 134

LOW = 0
HIGH = 1

def lcdSetWriteDir(g)
  g.setflags(LCD_D8, BsdGpio::OUTPUT)
  g.setflags(LCD_D9, BsdGpio::OUTPUT)
  g.setflags(LCD_D10, BsdGpio::OUTPUT)
  g.setflags(LCD_D11, BsdGpio::OUTPUT)
  g.setflags(LCD_D12, BsdGpio::OUTPUT)
  g.setflags(LCD_D13, BsdGpio::OUTPUT)
  g.setflags(LCD_D14, BsdGpio::OUTPUT)
  g.setflags(LCD_D15, BsdGpio::OUTPUT)
end

def lcdSetReadDir(g)
  g.setflags(LCD_D8, BsdGpio::INPUT)
  g.setflags(LCD_D9, BsdGpio::INPUT)
  g.setflags(LCD_D10, BsdGpio::INPUT)
  g.setflags(LCD_D11, BsdGpio::INPUT)
  g.setflags(LCD_D12, BsdGpio::INPUT)
  g.setflags(LCD_D13, BsdGpio::INPUT)
  g.setflags(LCD_D14, BsdGpio::INPUT)
  g.setflags(LCD_D15, BsdGpio::INPUT)
end

def lcdWrite8(g, data)
  g.set(LCD_D8, data & 1)
  g.set(LCD_D9, (data & 2) >> 1)
  g.set(LCD_D10, (data & 4) >> 2)
  g.set(LCD_D11, (data & 8) >> 3)
  g.set(LCD_D12, (data & 16) >> 4)
  g.set(LCD_D13, (data & 32) >> 5)
  g.set(LCD_D14, (data & 64) >> 6)
  g.set(LCD_D15, (data & 128) >> 7)
end

def lcdRead8(g)
  result = g.get(LCD_D15)
  result =  result << 1
  result = result | g.get(LCD_D14)
  result =  result << 1
  result = result | g.get(LCD_D13)
  result =  result << 1
  result = result | g.get(LCD_D12)
  result =  result << 1
  result = result | g.get(LCD_D11)
  result =  result << 1
  result = result | g.get(LCD_D10)
  result =  result << 1
  result = result | g.get(LCD_D9)
  result =  result << 1
  result = result | g.get(LCD_D8)
  return result
end

def lcdReadData8(g)
  lcdSetReadDir(g)
  g.set(LCD_CS, LOW)
  g.set(LCD_RS, HIGH)
  g.set(LCD_RD, HIGH)
  g.set(LCD_WR, HIGH)

  g.set(LCD_RD, LOW)
  usleep(10*1000)
  result = lcdRead8(g)
  g.set(LCD_RD, HIGH)

  usleep(10*1000)
  return result

end

def lcdWriteData(g, data)
  lcdSetWriteDir(g)
  g.set(LCD_CS, LOW)
  g.set(LCD_RS, HIGH)
  g.set(LCD_RD, HIGH)
  g.set(LCD_WR, HIGH)

  lcdWrite8(g, data >> 8)

  g.set(LCD_WR, LOW)
  usleep 10*1000
  g.set(LCD_WR, HIGH)

  lcdWrite8(g, data & 0xff)

  g.set(LCD_WR, LOW)
  usleep 10*1000
  g.set(LCD_WR, HIGH)

  g.set(LCD_CS, HIGH)
end

def lcdWriteCommand(g, command)
  lcdSetWriteDir(g)
  g.set(LCD_CS, LOW)
  g.set(LCD_RS, LOW)
  g.set(LCD_RD, HIGH)
  g.set(LCD_WR, HIGH)
  lcdWrite8(g, command >> 8)
  g.set(LCD_WR, LOW)
  usleep 10*1000
  g.set(LCD_WR, HIGH)
  lcdWrite8(g, command & 0xff)
  g.set(LCD_WR, LOW)
  usleep 10*1000
  g.set(LCD_WR, HIGH)
  g.set(LCD_CS, HIGH)
end

def lcdReset(g)
  g.set(LCD_RST, LOW)
  sleep 1
  g.set(LCD_RST, HIGH)
  sleep 1
end

def lcdInit(g)
  g.setflags(LCD_CS, BsdGpio::OUTPUT)
  g.set(LCD_CS, HIGH)
  g.setflags(LCD_RS, BsdGpio::OUTPUT)
  g.set(LCD_RS, HIGH)
  g.setflags(LCD_WR, BsdGpio::OUTPUT)
  g.set(LCD_WR, HIGH)
  g.setflags(LCD_RD, BsdGpio::OUTPUT)
  g.set(LCD_RD, HIGH)
  g.setflags(LCD_RST, BsdGpio::OUTPUT)
  g.set(LCD_RST, HIGH)
end

def readReg(g, reg, n, str)
  print "reg(" + reg.to_s + ") "
  lcdReset(g)
  lcdSetWriteDir(g)
  lcdWriteCommand(g, 0xB0)
  lcdWriteData(g, 0x00)
  lcdWriteCommand(g, reg)
  lcdSetReadDir(g)
  n.times {
    v = lcdReadData8(g)
    print v.to_s(16) + " "
  }
  lcdSetWriteDir(g)
  print "  " + str + "¥n"
end

g = BsdGpio.new(0)
lcdInit(g)
readReg(g, 0x00, 2, "ID: ILI9320, ILI9325, ILI9335, ...")
```

実行結果

```
# /usr/local/bin/mruby LCD_ID_readreg.rb
reg(0) 93 25   ID: ILI9320, ILI9325, ILI9335, ...
```
HardwareがらみのHackの一歩目はデバイスの認識です。

こちらのコードを参考にして表示を試してみました。

https://github.com/nopnop2002/ili9325_rpi

![写真（2019-04-14 17.20）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/6f7a08ce-f81b-e7d2-efe0-d325d7c89d5e.jpeg)

とっても遅いです。

上記のコードをベースにcairoでも書いてみました。

```ruby
def lcdWriteRegisterWord(g, addr, data)
  lcdWriteCommand(g, addr)
  lcdWriteData(g, data)
end

def lcdSetup(g)
  lcdWriteRegisterWord(g,0x00e5,0x8000)
  lcdWriteRegisterWord(g,0x0000,0x0001)
  lcdWriteRegisterWord(g,0x0001,0x0100)
  lcdWriteRegisterWord(g,0x0002,0x0700)
  lcdWriteRegisterWord(g,0x0003,0x1030)
  lcdWriteRegisterWord(g,0x0004,0x0000)
  lcdWriteRegisterWord(g,0x0008,0x0202)
  lcdWriteRegisterWord(g,0x0009,0x0000)
  lcdWriteRegisterWord(g,0x000a,0x0000)
  lcdWriteRegisterWord(g,0x000c,0x0000)
  lcdWriteRegisterWord(g,0x000d,0x0000)
  lcdWriteRegisterWord(g,0x000f,0x0000)
  lcdWriteRegisterWord(g,0x0010,0x0000)
  lcdWriteRegisterWord(g,0x0011,0x0000)
  lcdWriteRegisterWord(g,0x0012,0x0000)
  lcdWriteRegisterWord(g,0x0013,0x0000)
  lcdWriteRegisterWord(g,0x0010,0x17b0)
  lcdWriteRegisterWord(g,0x0011,0x0037)
  lcdWriteRegisterWord(g,0x0012,0x0138)
  lcdWriteRegisterWord(g,0x0013,0x1700)
  lcdWriteRegisterWord(g,0x0029,0x000d)
  lcdWriteRegisterWord(g,0x0020,0x0000)
  lcdWriteRegisterWord(g,0x0021,0x0000)
  lcdWriteRegisterWord(g,0x0030,0x0001)
  lcdWriteRegisterWord(g,0x0031,0x0606)
  lcdWriteRegisterWord(g,0x0032,0x0304)
  lcdWriteRegisterWord(g,0x0033,0x0202)
  lcdWriteRegisterWord(g,0x0034,0x0202)
  lcdWriteRegisterWord(g,0x0035,0x0103)
  lcdWriteRegisterWord(g,0x0036,0x011d)
  lcdWriteRegisterWord(g,0x0037,0x0404)
  lcdWriteRegisterWord(g,0x0038,0x0404)
  lcdWriteRegisterWord(g,0x0039,0x0404)
  lcdWriteRegisterWord(g,0x003c,0x0700)
  lcdWriteRegisterWord(g,0x003d,0x0a1f)
  lcdWriteRegisterWord(g,0x0050,0x0000)
  lcdWriteRegisterWord(g,0x0051,0x00ef)
  lcdWriteRegisterWord(g,0x0052,0x0000)
  lcdWriteRegisterWord(g,0x0053,0x013f)
  lcdWriteRegisterWord(g,0x0060,0x2700)
  lcdWriteRegisterWord(g,0x0061,0x0001)
  lcdWriteRegisterWord(g,0x006a,0x0000)
  lcdWriteRegisterWord(g,0x0090,0x0010)
  lcdWriteRegisterWord(g,0x0092,0x0000)
  lcdWriteRegisterWord(g,0x0093,0x0003)
  lcdWriteRegisterWord(g,0x0095,0x0101)
  lcdWriteRegisterWord(g,0x0097,0x0000)
  lcdWriteRegisterWord(g,0x0098,0x0000)
  lcdWriteRegisterWord(g,0x0007,0x0021)
  lcdWriteRegisterWord(g,0x0007,0x0031)
  lcdWriteRegisterWord(g,0x0007,0x0173)
end

def lcdDrawPixel(g, x, y, color)
  lcdWriteRegisterWord(g, 0x0020, x)
  lcdWriteRegisterWord(g, 0x0021, y)
  lcdWriteRegisterWord(g, 0x0022, color)
end

def rgb565_conv(r, g, b)
  rr = (r >> 3) << 11
  gg = (g >> 2) << 5
  bb = (b >> 3)
  return rr | gg | bb
end

def lcdCopy(g, c)
  for i in 1..320 do
    rgba = c.getpix(0, i - 1, 240)
    for n in 1..240 do
      color = rgb565_conv(rgba[2 + (n - 1) * 4], rgba[1 + (n - 1) * 4],
        rgba[0 + (n - 1) * 4])
      lcdDrawPixel(g, n - 1, i - 1, color)
    end
  end
end

g = BsdGpio.new(0)
lcdInit(g)
lcdReset(g)
lcdSetup(g)

c = Cairo.new(240, 320)
c.set_source_rgb(1 , 0, 0)
c.move_to(0, 0)
c.line_to(100, 100)
c.stroke()

lcdCopy(g, c)
```

lcdCopyのコードはAtheros(MIPS)で使っていたコードを参考にしたが、AtherosはBigendianなのでrbgaの並びが逆でした。

![写真（2019-04-15 17.13） #2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/7303a4c9-dda0-fc3d-295c-4a4eb2eeb133.jpeg)

なぜか白いままで表示できなくなってしまいました。初期化をいろいろためしたのですがダメでした。IDは拾えるのでパネルが壊れてしまったのかな。。。

突然復活しました。またおかしくなるのかもしれません。(2019/09/30)

どうも起動時に負荷の重い状態で初期化をするとパネルがハングアップしてしまうような感じのようです。