FreeBSDが動いているOnion OmegaにAitendoで購入した小型液晶を接続してmrubyで表示を試してみました。
液晶のコントローラーはSitronixのST7735Bで128x160の表示ができます。
LinuxとラズパイとPythonで試されているこちらのページを参考にさせてもらいました。
接続は以下のように行っています。
SPI接続なのですが、ResetとRSというデータの種別を指定する信号が別に必要でこれらはGPIOで制御します。またSPIのデータ読み込みのためのMISOは接続されていません。
FreeBSDでユーザランドからSPIをコントロールするためのドライバspigenをmrubyから制御するためにmruby-bsdspiというgemを作ってみました。
以下をbuild_config.rbに追加してmrubyをビルドします。
conf.gem :git => 'https://github.com/yamori813/mruby-bsdgpio.git'
conf.gem :git => 'https://github.com/yamori813/mruby-bsdspi.git'
#
# 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
今のところ画面全体の表示に5分くらいかかってしまい、実用になりません。。。oz_
追記:gpiospiのwaitをなくして、1K単位でのブロック転送にしたところ3秒くらいで表示できるようになりました。
追記:ユニバーサル基板を切って、シールドっぽくしてみました。