Waveshare Pico-CapTouch-ePaper-2.9 をCircuitpythonで使う

左手デバイス的なキーボードを作りたくてe-Paperタッチディスプレイを購入しました。
WaveshareのPico-CapTouch-ePaper-2.9と言う製品です。

Raspberry pi picoをひとまわり大きくしたサイズでとても可愛いですね。

動作確認

販売元のWikiにCとPythonの実装例があります。

www.waveshare.com

丁寧な説明があるので特につまずく事なく動作できました。少なくとも初期不良はなくて安心です。

CircuitPython

Wikiの例はMicroPythonでの実装でした。
最終的にはキーボードを作成したいので、HID関連のライブラリがあるCircuitPythonで動かしたいです。

仕様書を読むとドライバICとしてSSD1680が載っているようです。
ラッキーなことにCircuitPythonでSSD1680のライブラリがあるので利用できそうですね。

github.com

あれ?うまくいかない🤔

再挑戦

色々と試行錯誤しましたがどうにも動かないため、オリジナルをちょっと修正。
どうやら0x44と0x45のコマンドがうまくいってない感じなので、実現クラスのコンストラクタで強引にコマンドを送ってみたら動作しました。

ちょっと強引だけど動いたからいいか、自分に言い聞かせながら次に進むことにします・・. (ちなみにrotation=0もしくは90だとうまく動かないです・・)

import board
import busio
import displayio

_START_SEQUENCE = (
    b"\x12\x80\x14"  # soft reset and wait 20ms
    b"\x11\x01\x03"  # Ram data entry mode
    b"\x3C\x01\x05"  # border color
    b"\x2c\x01\x36"  # Set vcom voltage
    b"\x03\x01\x17"  # Set gate voltage
    b"\x04\x03\x41\x00\x32"  # Set source voltage
    b"\x4e\x01\x01"  # ram x count
    b"\x4f\x02\x00\x00"  # ram y count
    b"\x01\x03\x00\x00\x00"  # set display size
    b"\x44\x02\x01\x10" # 追加_SSD1680_SET_RAMXPOS
    b"\x45\x04\x00\x00\x00\x00" # 追加_SSD1680_SET_RAMYPOS
    b"\x22\x01\xf4"  # display update mode
)

_STOP_SEQUENCE = b"\x10\x81\x01\x64"  # Deep Sleep

class SSD1680(displayio.EPaperDisplay):
  def __init__(self, bus: displayio.Fourwire, **kwargs):
    stop_sequence = bytearray(_STOP_SEQUENCE)
    try:
      bus.reset()
    except RuntimeError:
      # No reset pin defined, so no deep sleeping
      stop_sequence = b""

    start_sequence = bytearray(_START_SEQUENCE)
    width = kwargs["width"]
    height = kwargs["height"]
    if "rotation" in kwargs and kwargs["rotation"] % 180 != 90:
        width, height = height, width
    start_sequence[29] = (width - 1) & 0xFF
    start_sequence[30] = ((width - 1) >> 8) & 0xFF
    # ここ追加
    start_sequence[40] = (width - 1) & 0xFF
    start_sequence[41] = ((width - 1) >> 8) & 0xFF

    super().__init__(
      bus,
      start_sequence,
      stop_sequence,
      **kwargs,
      ram_width=250,
      ram_height=296,
      busy_state=True,
      write_black_ram_command=0x24,
      write_color_ram_command=0x26,
      black_bits_inverted=False,
      # コメントアウト
      # set_column_window_command=0x44,
      # set_row_window_command=0x45,
      set_current_column_command=0x4E,
      set_current_row_command=0x4F,
      refresh_display_command=0x20,
      colstart=1,
      always_toggle_chip_select=True,
    )

displayio.release_displays()

spi = busio.SPI(clock=board.GP10, MOSI=board.GP11)
epd_cs = board.GP9
epd_dc = board.GP8
epd_reset = board.GP12
epd_busy = board.GP13

display_bus = displayio.FourWire(
    spi,
    command=epd_dc,
    chip_select=epd_cs,
    reset=epd_reset,
    baudrate=1000000
)

display = SSD1680(
  display_bus,
  width=296,
  height=128,
  busy_pin=epd_busy,
  highlight_color=0xFF0000,
  rotation=270
)

g = displayio.Group()
with open("/kakugen.bmp", "rb") as f:
  pic = displayio.OnDiskBitmap(f)
  t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader)
  g.append(t)
  display.show(g)
  display.refresh()

次回

次はタッチの取得をポーティングしてみます。