0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MachiKania type PでST7789 LCDを使用する

Posted at

はじめに

MachiKaniaがサポートしている液晶ディスプレイはILI9341搭載QVGA(320x240)またはILI9488搭載480x320でSPI接続のものなのでそれ以外の制御チップを使用しているディスプレイは接続できないとが試しにST7789搭載の液晶ディスプレイを接続したらグラフィックsなど表示できたがファイル選択などの画面は表示しない部分やひょじじたいがおかしくなってしまった。そこでST7789搭載の液晶ディスプレイを利用するプログラムの作成を試みた。

検証環境

以下の環境でプログラムの作成と検証を行ないました。

  • macOS : Tahoe 26.0.1
  • PicoCalc : Raspberry Pi Pico
  • MachiKania : Phyllosoma 1.6.0

使用部品

下記の部品を使用しました。

配線

Raspberry Pi PicoとST7789搭載液晶ディスプレイはSPI1で接続し、各端子は次のように配線しました。Picoの()内の数値はRaspberry Pi Picoの物理ピン番号です。

ST7789 Pico
GND GND(38)
VCC 3V3(36)
SCL GP10(14)
SDA GP11(15)
RST GP21(27)
DC GP22(29)
CS GP5(7)

配線図を以下に示します。

MachiKania-ST7789_ブレッドボード.png

MachiKaniaのSPIピン設定

MachiKaniaはSPI出使用するRaspberry Pi Picoのピン番号を設定ファイルMACHIKAP.INIに記述しておく。上記の敗戦にあわせて下記の設定をしました。

SPIMISO=8
SPIMOSI=11
SPICLK=10

ST7789搭載液晶ディスプレイを利用する流れ

ST7789を搭載した液晶ディスプレイを使用するまでの流れは次のとおりです。

  1. SPIのチャンネルを開く
  2. ST7789の初期化
  3. 描画の実行

SPIのチャンネルを開く

MachiKaniaではSPIで使用するピンをファイルMACHIKAP.INIに記載しているのでBASICのコードではSPIの動作周波数、転送データ幅、SPIモード、CSピンを指定するだけでよい。今回は周波数20MHz、データ幅8ビット、モード2、物理ピン5(GP3)をCSとしました。また、液晶ディスプレイのRESETピン、CSピンをハイレベルに設定します。コードは次のとおりです。

WAIT 120
SPI 20000, 8, 2, 5
DELAYMS 300
OUT 11, 1 : OUT 12, 1

ST7789初期化

以前、Raspberry Pi PicoでPicoMite(MMBasic)を使う〜CSなしST7789 LCDを動かすで使用したコードをKM-BASICのコードに変換し、さらにフレームレートなどの設定を追加しました。下記がそのコードで、サブルーチンINITとして定義しています。その他のサブルーチンについては後述します。

LABEL INIT
  REM ハードリセット
  OUT 11, 1 : DELAYMS 10
  OUT 11, 0 : DELAYMS 10
  OUT 11, 1 : DELAYMS 120

  GOSUB SCMD, $01 : REM SWRESET
  DELAYMS 150
  GOSUB SCMD, $11 : REM SLPOUT
  DELAYMS 120

  REM 16bitカラー ,RGB565
  GOSUB SCMD, $3A : GOSUB SDATA, $55

  REM MADCTL : ポートレートモードに
  GOSUB SCMD, $36 : GOSUB SDATA, $00

  REM フレームレート等の設定
  GOSUB SCMD, $B2
  POKE BUF,    $0C : POKE BUF+ 1, $0C
  POKE BUF+ 2, $00 : POKE BUF+ 3, $33
  POKE BUF+ 4, $33
  GOSUB SDBLK, BUF, 5
  GOSUB SCMD, $B7 : GOSUB SDATA, $35
  GOSUB SCMD, $BB : GOSUB SDATA, $19
  GOSUB SCMD, $C0 : GOSUB SDATA, $2C
  GOSUB SCMD, $C2 : GOSUB SDATA, $01
  GOSUB SCMD, $C3 : GOSUB SDATA, $12
  GOSUB SCMD, $C4 : GOSUB SDATA, $20
  GOSUB SCMD, $C6 : GOSUB SDATA, $0F
  GOSUB SCMD, $D0 : GOSUB SDATA, $A4 : GOSUB SDATA, $A1

  REM ディスプレイをオンに
  GOSUB SCMD, $29
  DELAYMS 100
RETURN

コマンド送信サブルーチン SCMD

ST7789にコマンドを1バイトのコマンドを送信するサブルーチンSCMDを次のように定義しました。CSをローレベルにして、SPIWRITE命令で引数のデータを送信します。

LABEL SCMD
  VAR C
  C = ARGS(1)
  OUT 12, 0 : REM CSをローに
  SPIWRITE C
RETURN

データ送信サブルーチン SDATA

ST7789にコマンド送信後に1バイトのデータを送信するサブルーチンSDATAを次のように定義しました。CSをハイレベルにして、SPIWRITE命令でサブルーチンの引数のデータを送信します。

LABEL SDATA
  VAR D
  OUT 12, 1 : REM CSをハイに
  D = ARGS(1)
  SPIWRITE D
RETURN

データのバルク送信サブルーチン SDBLK

ST7789にコマンド送信後に複数個のデータを送信するサブルーチンSDBLKを次のように定義しました。CSをハイレベルにして、SPIWRTIEDATA命令でサブルーチンの最初の引数のバッファアドレスから二番目の引数の個数分のデータを送信します。

LABEL SDBLK
  VAR B,N
  B = ARGS(1) : N = ARGS(2)
  OUT 12, 1
  SPIWRITEDATA B, N
RETURN

データ転送先領域指定サブルーチン SAWIN

ST7789ではデータ転送先領域の横方向の範囲をコマンド2AH、縦方向の範囲をコマンド2BHを送信後に始点・終点の順にまとめて送信しておきます。
この範囲指定後に指定領域分の描画データをまとめて送信するとディスプレイに表示されます。

LABEL SAWIN
  VAR X0,X1,Y0,Y1

  X0 = ARGS(1) : Y0 = ARGS(2)
  X1 = ARGS(3) : Y1 = ARGS(4)

  GOSUB SCMD, $2A
  POKE AWB,     X0 /256 : POKE AWB + 1, X0 % 256
  POKE AWB + 2, X1 /256 : POKE AWB + 3, X1 % 256
  GOSUB SDBLK, AWB, 4

  GOSUB SCMD, $2B
  POKE AWB,     Y0 /256 : POKE AWB + 1, Y0 % 256
  POKE AWB + 2, Y1 /256 : POKE AWB + 3, Y1 % 256
  GOSUB SDBLK, AWB, 4

  GOSUB SCMD, $2C
RETURN

描画機能

ST7789の初期化が完了したら文字などを描画できるようになります。今回は下記の機能をサブルーチンで作成しました。多くはChatGPTの力を借りて作成しています。

機能 サブルーチン名 引数
16ビットカラー生成 RGB565 RGBの各階調
一文字 DCHR 表示開始座標、文字、前景色、背景色
文字列 DSTR 表示開始座標、文字列、前景色、背景色
1ピクセル描画 DPXL 表示座標、色
直線 DLINE 始点と終点座標、色
長方形 RECT 描画開始座標、幅、高さ、線幅、色、塗りつぶしの有無
水平線 HLINE 表示開始座標、長さ、色
垂直線 VLINE 表示開始座標、長さ、色
DCIRCLE 中心座標、半径、線幅、色、塗りつぶしの有無
楕円 ELLIPSE 中心座標、縦径、横径、線幅、色、塗りつぶしの有無

16ビットカラー値算出サブルーチン RGB565

3つの引数に与えてRGBの8ビットの値から16ビットカーラを計算し、返すサブルーチン。ST7789が反転表示してしまうためRGBの値を255から引いて計算している。

LABEL RGB565
  VAR R,G,B,C
  R = ARGS(1) : G = ARGS(2) : B = ARGS(3)
  C = ((255 - R >> 3) << 11) OR ((255 - G >> 2) << 5) OR (255 - B >> 3) 
RETURN C

一文字描画サブルーチン DCHR

引数で指定した座標を表示する文字の左上座標として指定した前景色と背景色で描くサブルーチン。

文字データはMachiKaniaのシステムフォントのデータを一文字分読み取って前景色、背景色データをバッファに保管してまとめ、サブルーチンSAWINでバッファのデータを転送領域を指定し、サブルーチンSDBLKでまとめて転送します。MachiKaniaのIL9325.BASのprtメソッドのコードを利用しました。
ディスプレイの

ABEL DCHR
  VAR PX,PY,CH,FG,BG
  VAR A,I,P,D
  VAR ROW,PIX
  VAR FGH,FGL,BGH,BGL
  VAR COL
  REM 引数の値をローカル変数に代入
  PX = ARGS(1) : PY = ARGS(2) : CH$ = ARGS$(3)
  FG = ARGS(4) : BG = ARGS(5)
  REM 前景色、背景色を上位8ビット下位8ビットに分ける
  FGH = FG / 256 : FGL = FG % 256
  BGH = BG / 256 : BGL = BG % 256

  A = PEEK(CH) : IF A=0 THEN RETURN : REM 文字データを読み取り、
  P = SYSTEM(103) + A * 8 : REM フォントデータのアドレスを取得
  I = 0
  FOR ROW = 0 TO 7 : REM 行
    D = PEEK(P)    : REM フォンとデータの取得
    FOR PIX = 0 TO 7 : REM 1ドットごとの前景、背景の判断
      IF D AND $80 THEN
        POKE CBUF + I * 2, FGH : POKE CBUF + I * 2 + 1, FGL
      ELSE
        POKE CBUF + I * 2, BGH : POKE CBUF + I * 2 + 1, BGL
      ENDIF
      D=D<<1 : REM 次のドットを先頭にシフト
      I=I+1
    NEXT
    P=P+1 : REM 次の行へ
  NEXT
  REM フォンとデータの転送領域の指定
  GOSUB SAWIN, PX, PY, PX + 7, PY + 7
  GOSUB SCMD, $2C : REM メモリへの書き込み開始
  GOSUB SDBLK, CBUF, 8*2*8 : REM 書き込みデータをバルク転送
RETURN

文字列描画サブルーチン DSTR

文字描画サブルーチンDCHRを使って文字列を描画するサブルーチン。引数に与えられた文字列から一文字ずつ取り出して文字描画サブルーチンDCHRで描きます。
KM-BASICには他のBASICにあるMID$関数がないが文字列変数$(取り出す位置,取り出す文字数)で同様の機能を実現できる。

LABEL DSTR
  VAR PX,PY,TXT,FG,BG
  VAR K
  REM 引数の取得と格納
  PX=ARGS(1) : PY=ARGS(2) : TXT$=ARGS$(3)
  FG=ARGS(4) : BG=ARGS(5)
  REM 文字列の先頭から一文字ずつとり出し、文字描画サブルーチンDCHRで描画
  FOR K=0 TO LEN(TXT$)-1
    GOSUB DCHR, PX, PY, TXT$(K, 1), FG, BG
    PX = PX + 8
  NEXT
RETURN

1ピクセル描画サブルーチン DPXL

引数で指定した座標のピクセルに、引数で指定した色のデータを書き込むサブルーチン。

LABEL DPXL
  VAR X,Y,C
  REM 引数の取得と格納
  X = ARGS(1) : Y = ARGS(2) : C = ARGS(3)
  REM 色データを8ビットごとに分割
  POKE BUF, C / 256 : POKE BUF + 1, C % 256
  REM データ転送先の指定
  GOSUB SAWIN, X, Y, X, Y
  GOSUB SDBLK, BUF, 2 : REM 色データを転送
RETURN

直線描画サブルーチン DLINE

引数で指定した開始、終了座標間に指定した色の直線を描くサブルーチン。ChatGPTの力を借りて作りました。
1ピクセル描画サブルーチン DPXLを使って始点座標から終点座標に一つずつ点を描画することで直線を描いています。

LABEL DLINE
  VAR X0,X1,Y0,Y1,COL
  VAR SX,SY,ERR,E2

  REM 引数の取得と格納
  X0 = ARGS(1) : Y0 = ARGS(2)
  X1 = ARGS(3) : Y1 = ARGS(4)
  COL = ARGS(5)
  
  DX = ABS(X1 - X0) : DY = ABS(Y1 - Y0)
  IF X0 < X1 THEN SX = 1 ELSE SX = -1
  IF Y0 < Y1 THEN SY = 1 ELSE SY = -1
  IF DX > DY THEN
    ERR = DX / 2
  ELSE
    ERR = DY / 2
  ENDIF

  REM 1ピクセルずつ描画
  DO
    GOSUB DPXL, X0, Y0, COL    
    IF X0 = X1 AND Y0 = Y1 THEN BREAK
    E2 = ERR
    IF E2 > -DX THEN ERR = ERR - DY : X0 = X0 + SX
    IF E2 <  DY THEN ERR = ERR + Dx : Y0 = Y0 + SY
  LOOP
  
RETURN

長方形描画サブルーチン RECT

引数で指定した長方形の左上の座標から引数で指定した幅と高さの長方形を指定され線幅で描きます。塗りつぶし指定があると塗りつぶしの長方形が描かれます。このコードもChatGPTの力を借りました。
長方形の描画は水平線描がサブルーチンHLINEと垂直線描がサブルーチンVLINEを使用しています。

LABEL RECT
  VAR X0,Y0,X1,Y1
  VAR W,H,T,COL,FILL
  VAR I

  REM 引数の取得と格納
  X0 = ARGS(1) : Y0 = ARGS(2)
  W  = ARGS(3) : H  = ARGS(4)
  T  = ARGS(5) : COL = ARGS(6) : FILL = ARGS(7)

  REM 終点の算出
  X1 = X0 + W - 1 : Y1 = Y0 + H - 1

  REM 塗りつぶし指定が有る場合は水平線描サブルーチンHLINEで描く
  IF FILL != 0 THEN
    FOR I = Y0 + T TO Y1 - T
      GOSUB HLINE, X0+T, I, W-2*T, COL
    NEXT
  ENDIF
  
  REM 上下の枠の描画
  FOR I = 0 TO T - 1
    GOSUB HLINE, X0, Y0+I, W, COL
    GOSUB HLINE, X0, Y1-I, W, COL
  NEXT

  REM 左右の枠の指定
  FOR I = 0 TO T - 1
    GOSUB VLINE, X0+I, Y0, H, COL
    GOSUB VLINE, X1-I, Y0, H, COL
  NEXT
RETURN

水平線描画サブルーチン HLINE

水平線を描くサブルーチンです。
描画するデータをバッファにまとめて格納し、指定した領域にバルク転送します。

LABEL HLINE
  VAR X,Y,L,COL
  VAR HI,LO
  VAR I

  REM 引数の取得と格納
  X = ARGS(1) : Y = ARGS(2) : L = ARGS(3) : COL = ARGS(4)

  HI = COL / 256 : LO = COL % 256 : REM 色データの分離
  
  REM 色データをバッファに格納
  FOR I=0 TO L
    POKE BUF + 2 * I,     HI
    POKE BUF + 2 * I + 1, LO
  NEXT

  REM データ転送領域を指定し、水平線データを転送
  GOSUB SAWIN, X, Y, X+L-1, Y
  GOSUB SCMD, $2C
  GOSUB SDBLK, BUF, L * 2
RETURN

垂直線描画サブルーチン VLINE

垂直線を描くサブルーチンです。水平線と同様に描画するデータをバッファにまとめて格納し、指定領域にバルク転送しています。

LABEL VLINE
  VAR X,Y,L,COL
  VAR HI,LO
  VAR I
  REM 引数の取得と格納
  X = ARGS(1) : Y = ARGS(2) : L = ARGS(3) : COL = ARGS(4)
  
  REM 色データをバッファに格納
  HI = COL / 256 : LO = COL % 256
  FOR I=0 TO L - 1
    POKE BUF + 2 * I,     HI
    POKE BUF + 2 * I + 1, LO
  NEXT
  
  REM データ転送領域を指定し、水平線データを転送
  GOSUB SAWIN, X, Y, X, Y+L-1
  GOSUB SCMD, $2C
  GOSUB SDBLK, BUF, L * 2

RETURN

円描画サブルーチン DCIRCLE

引数で指定した中心座標、半径、線幅、色の円あるいは塗りつぶし円を描きます。

LABEL DCIRCLE
  VAR CX,CY,R,T,COL,FILL
  VAR Y,XOUT,XIN,RIN

  REM 引数の取得と格納
  CX = ARGS(1) : CY = ARGS(2)
  R  = ARGS(3) : T  = ARGS(4)
  COL= ARGS(5) : FILL=ARGS(6)

  IF T < 1 THEN T = 1
  IF R-T+1 > 0 THEN RIN=R-T+1 ELSE RIN=0

  FOR Y = -R TO R
    XOUT = INT(SQRT#(FLOAT#(R*R - Y*Y)) + 0.5)
    IF FILL=1 THEN
      GOSUB HLINE, CX-XOUT, CY+Y, 2*XOUT+1, COL
    ELSE
      GOSUB DPXL, CX-XOUT, CY+Y, COL
      GOSUB DPXL, CX+XOUT, CY+Y, COL
    ENDIF

    IF NOT(FILL) AND RIN > 0 THEN
      IF ABS(Y) < RIN THEN
        XIN = INT(SQRT#(FLOAT#(RIN * RIN - Y*Y)) + 0.5)
      ENDIF
    ENDIF
  NEXT
RETURN

楕円描画サブルーチン ELLIPSE

引数で指定した中心座標、横径、縦径、線幅、色の楕円あるいは塗りつぶし楕円を描きます。

LABEL ELLIPSE
  VAR CX,CY,HDIAM,VDIAM,T,COL,FILL
  VAR INNERRX,INNERRY
  VAR Y,XOUT,XIN,FRAC,RX,RY

  REM 引数の取得と格納
  CX    = ARGS(1) : CY = ARGS(2)
  VDIAM = ARGS(3) : HDIAM = ARGS(4)
  T     = ARGS(5) : COL = ARGS(6)
  FILL  = ARGS(7)

  IF T < 1 THEN T = 1
  RX = HDIAM / 2
  RY = VDIAM / 2

  IF RX <= 0 OR RY <= 0 THEN RETURN

  IF RX - T + 1 > 0 THEN INNERRX = RX -T + 1 ELSE INNERRX = 0
  IF RY - T + 1 > 0 THEN INNERRY = RY -T + 1 ELSE INNERRY = 0

  FOR Y = -RY TO RY 
    FRAC# = 1.0 - FLOAT#(Y * Y) / FLOAT#(RY * RY)
    IF FRAC# < 0 THEN FRAC# = 0
    XOUT = INT(FLOAT#(RX) * SQRT#(FRAC#) + 0.5)
    
    IF FILL = 1 THEN
      GOSUB HLINE,CX-XOUT, CY+Y, 2*XOUT+1, COL
    ELSE
      IF INNERRX=0 OR INNERRY=0 THEN
	GOSUB DPXL, CX-XOUT, CY+Y, COL
	GOSUB DPXL, CX+XOUT, CY+y, COL
      ELSE
        FRAC# = 1.0 - FLOAT#(Y*Y)/FLOAT#(INNERRY*INNERRY)
        IF FRAC# < 0 THEN
          XIN = -1
        ELSE
          XIN = INT(FLOAT#(INNERRX) * SQRT#(FRAC#) + 0.5)
        ENDIF

        IF XIN < 0 THEN
          GOSUB HLINE, CX-XOUT, CY+Y, 2*XOUT+1, COL
        ELSEIF XOUT > XIN THEN
          GOSUB HLINE, CX-XOUT,  CY+Y, XOUT-XIN, COL
	  GOSUB HLINE, CX+XIN+1, CY+Y, XOUT-XIN, COL
	ENDIF
      ENDIF
    ENDIF
  NEXT

RETURN

画面クリアサブルーチン CLSC

画面を指定した色でクリアするサブルーチンです。
画面の上から一行ずつの指定した色データをまとめて転送して画面をクリアしています。

LABEL CLSC
  VAR COL,I,Y

  COL = ARGS(1)
  FOR I = 0 TO 239
    POKE BUF + I * 2,     COL / 256
    POKE BUF + I * 2 + 1, COL % 256
  NEXT
  GOSUB SAWIN, 0, 0, 239, 319
  FOR Y = 0 TO D319
    GOSUB SDBLK, BUF, 480
  NEXT
RETURN

すべてのコード

下記が上記のサブルーチンを含んだ文字列、図形の描画のコードです。

ST7789TS.BAS
REM ST7789用の機能を作成
USETIMER 100
USEVAR COL
USEVAR X0, X1, Y0, Y1
USEVAR ERR, E2
USEVAR DX, DY, SX, SY
USEVAR FILL, HI, LO
USEVAR CH, FG, BG, TXT
USEVAR FGH, FGL, BGH, BGL
USEVAR ROW, PIX, MASK, BUF
USEVAR CBUF : REM 1文字分のバッファ
USEVAR AWB  : REM アドレスウィンドウ用バッファ
USEVAR PX, PY
USEVAR CC
USEVAR CX, CY, XOUT,XIN
USEVAR INNERRX, INNERRY, FRAC
USEVAR HDIAM, VDIAM
USEVAR RX, RY,RIN

REM バッファ
DIM BUF(480/4)
DIM CBUF(8*2*8/4)
DIM AWB(4)

USEGRAPHIC

Dim CC(10) : REM COLOR
REM 色定義
CC(0) = GOSUB(RGB565(  0,   0,   0) : REM Black
CC(1) = GOSUB(RGB565(  0,   0, 255) : REM Blue
CC(2) = GOSUB(RGB565(  0, 255,   0) : REM Green
CC(3) = GOSUB(RGB565(  0, 161, 233) : REM Cyan
CC(4) = GOSUB(RGB565(255,   0,   0) : REM Red
CC(5) = GOSUB(RGB565(228,   0, 127) : REM Magenta
CC(6) = GOSUB(RGB565(255, 255,   0) : REM Yellow
CC(7) = GOSUB(RGB565(128, 128, 128) : REM Gray
CC(8) = GOSUB(RGB565(165,  42,  42) : REM Brown
CC(9) = GOSUB(RGB565(255, 165,   0) : REM Orange
CC(10) = GOSUB(RGB565(255, 255, 255) : REM White

REM Open SPI
WAIT 120
SPI 20000, 8, 2, 5
DELAYMS 300
REM Set DC & Reset pin to HIGH
OUT 11, 1 : OUT 12, 1

GOSUB INIT,0      : REM ST7789の初期化
GOSUB CLSC, CC(0) : REM 画面を黒でクリア

REM 文字列描画
GOSUB DSTR, 10,  0, "Hello ST7789", CC(10), CC(0)
GOSUB DSTR, 10, 10, "RED red",      CC(4),  CC(0)
GOSUB DSTR, 10, 20, "GREEN green",  CC(2),  CC(0)
GOSUB DSTR, 10, 30, "BLUE blue",    CC(1),  CC(0)

USEVAR XX1, XX2, YY1, YY2
XX1 = 0 : XX2 =  0
YY1 = 0 : YY2 = 50

REM ASCIIテーブルの表示
FOR I = $20 TO $7E
  GOSUB DCHR, XX2, YY2, CHR$(I), CC(10), CC(0)
  XX1 = XX1 + 16
  XX2 = XX2 + 8
  IF (I -16)  % 16 = 15 THEN
    XX1 = 0 : XX2 = 0
    YY1 = YY1 + 24 : YY2 = YY2 + 12
  ENDIF
NEXT

REM 直線描が
FOR I= 0 TO 10
  GOSUB DLINE, 130, I * 4, 239, I * 4, CC(I)
NEXT

REM 長方形描画
FOR I=1 TO 10
  GOSUB RECT, 130,  50, I*10, I* 3, 2, CC(I), 0
NEXT

REM 塗りつぶし長方形
GOSUB RECT, 130, 110, 100, 50, 1, CC(2), 1

REM 同心円描画
FOR R=1 TO 10
  GOSUB DCIRCLE, 40, 160, R*3, 3, CC(R), 0
NEXT

REM 塗りつぶし円描画
GOSUB DCIRCLE, 110, 160, 30, 1, CC(4), 1

REM 楕円描画
GOSUB Ellipse,  80, 240, 50, 80, 3, CC(5), 0
GOSUB Ellipse, 180, 240 ,60, 90, 1, CC(6), 1
END

REM === 以下サブルーチン郡 ===
LABEL SCMD
  VAR C
  C = ARGS(1)
  OUT 12, 0
  SPIWRITE C
RETURN

REM --------------------------------
LABEL SDATA
  VAR D
  OUT 12, 1
  D = ARGS(1)
  SPIWRITE D
RETURN

REM --------------------------------
LABEL SDBLK
  VAR B,N
  B = ARGS(1) : N = ARGS(2)
  OUT 12, 1
  SPIWRITEDATA B, N
RETURN

REM --------------------------------
REM アドレスウィンドウ
LABEL SAWIN
  VAR X0,X1,Y0,Y1

  X0 = ARGS(1) : Y0 = ARGS(2)
  X1 = ARGS(3) : Y1 = ARGS(4)

  GOSUB SCMD, $2A
  POKE AWB,     X0 /256 : POKE AWB + 1, X0 % 256
  POKE AWB + 2, X1 /256 : POKE AWB + 3, X1 % 256
  GOSUB SDBLK, AWB, 4

  GOSUB SCMD, $2B
  POKE AWB,     Y0 /256 : POKE AWB + 1, Y0 % 256
  POKE AWB + 2, Y1 /256 : POKE AWB + 3, Y1 % 256
  GOSUB SDBLK, AWB, 4

  GOSUB SCMD, $2C
RETURN

REM --------------------------------
REM Initialize
LABEL INIT
  VAR M : REM 0=Portrait,1=Landscape
  M = ARGS(1)
  REM Hard reset
  OUT 11, 1 : DELAYMS 10
  OUT 11, 0 : DELAYMS 10
  OUT 11, 1 : DELAYMS 120

  GOSUB SCMD, $01 : REM SWRESET
  DELAYMS 150
  GOSUB SCMD, $11 : REM SLPOUT
  DELAYMS 120

  REM Color : 16bit,565
  GOSUB SCMD, $3A : GOSUB SDATA, $55
  REM MADCTL : Portrait
  GOSUB SCMD, $36 : GOSUB SDATA, $00
  ENDIF

  GOSUB SCMD, $B2

  POKE BUF,    $0C : POKE BUF+ 1, $0C
  POKE BUF+ 2, $00 : POKE BUF+ 3, $33
  POKE BUF+ 4, $33

  GOSUB SDBLK, BUF, 5

  GOSUB SCMD, $B7 : GOSUB SDATA, $35
  GOSUB SCMD, $BB : GOSUB SDATA, $19
  GOSUB SCMD, $C0 : GOSUB SDATA, $2C
  GOSUB SCMD, $C2 : GOSUB SDATA, $01
  GOSUB SCMD, $C3 : GOSUB SDATA, $12
  GOSUB SCMD, $C4 : GOSUB SDATA, $20
  GOSUB SCMD, $C6 : GOSUB SDATA, $0F
  GOSUB SCMD, $D0 : GOSUB SDATA, $A4 : GOSUB SDATA, $A1

  GOSUB SCMD, $29
  DELAYMS 100
RETURN

REM --------------------------------
LABEL RGB565
  VAR R,G,B,C
  R = ARGS(1) : G = ARGS(2) : B = ARGS(3)
  C = ((255 - R >> 3) << 11) OR ((255 - G >> 2) << 5) OR (255 - B >> 3) 
RETURN C


REM --------------------------------
LABEL DPXL
  VAR X,Y,C

  X = ARGS(1) : Y = ARGS(2) : C = ARGS(3)
  GOSUB SAWIN, X, Y, X, Y
  POKE BUF, C / 256 : POKE BUF + 1, C % 256
  GOSUB SDBLK, BUF, 2
RETURN

REM --- LINE(X0, Y0, X1, Y1, COL)
LABEL DLINE
  VAR X0,X1,Y0,Y1,COL
  VAR SX,SY,ERR,E2

  X0 = ARGS(1) : Y0 = ARGS(2)
  X1 = ARGS(3) : Y1 = ARGS(4)
  COL = ARGS(5)
  
  DX = ABS(X1 - X0) : DY = ABS(Y1 - Y0)
  IF X0 < X1 THEN SX = 1 ELSE SX = -1
  IF Y0 < Y1 THEN SY = 1 ELSE SY = -1
  IF DX > DY THEN
    ERR = DX / 2
  ELSE
    ERR = DY / 2
  ENDIF
    
  DO
    GOSUB DPXL, X0, Y0, COL    
    IF X0 = X1 AND Y0 = Y1 THEN BREAK
    E2 = ERR
    IF E2 > -DX THEN ERR = ERR - DY : X0 = X0 + SX
    IF E2 <  DY THEN ERR = ERR + Dx : Y0 = Y0 + SY
  LOOP
  
RETURN

REM --- RECT x0,y0,w,h,t,col,fill
LABEL RECT
  VAR X0,Y0,X1,Y1
  VAR W,H,T,COL,FILL
  VAR I

  X0 = ARGS(1) : Y0 = ARGS(2)
  W  = ARGS(3) : H  = ARGS(4)
  T  = ARGS(5) : COL = ARGS(6) : FILL = ARGS(7)

  X1 = X0 + W - 1 : Y1 = Y0 + H - 1

  IF FILL != 0 THEN
    FOR I = Y0 + T TO Y1 - T
      GOSUB HLINE, X0+T, I, W-2*T, COL
    NEXT
  ENDIF

  FOR I = 0 TO T - 1
    GOSUB HLINE, X0, Y0+I, W, COL
    GOSUB HLINE, X0, Y1-I, W, COL
  NEXT

  FOR I = 0 TO T - 1
    GOSUB VLINE, X0+I, Y0, H, COL
    GOSUB VLINE, X1-I, Y0, H, COL
  NEXT
RETURN

REM --- HLINE X,Y,L,COL--------------------------
LABEL HLINE
  VAR X,Y,L,COL
  VAR HI,LO
  VAR I

  X = ARGS(1) : Y = ARGS(2) : L = ARGS(3) : COL = ARGS(4)

  HI = COL / 256 : LO = COL % 256
  FOR I=0 TO L
    POKE BUF + 2*I, HI
    POKE BUF + 2*I + 1, LO
  NEXT

  GOSUB SAWIN, X, Y, X+L-1, Y
  GOSUB SCMD, $2C
  GOSUB SDBLK, BUF, L * 2
RETURN

REM --- VLINE x,y,l,col
LABEL VLINE
  VAR X,Y,L,COL
  VAR HI,LO
  VAR ROW

  X = ARGS(1) : Y = ARGS(2) : L = ARGS(3) : COL = ARGS(4)

  HI = COL / 256 : LO = COL % 256
  FOR ROW=0 TO L - 1
    POKE BUF + 2 * ROW,     HI
    POKE BUF + 2 * ROW + 1, LO
  NEXT

  GOSUB SAWIN, X, Y, X, Y+L-1
  GOSUB SCMD, $2C
  GOSUB SDBLK, BUF, L * 2

RETURN

REM --- Circle cx,cy,r,t,col,fill
LABEL DCIRCLE
  VAR CX,CY,R,T,COL,FILL
  VAR Y,XOUT,XIN,RIN

  CX = ARGS(1) : CY = ARGS(2)
  R  = ARGS(3) : T  = ARGS(4)
  COL= ARGS(5) : FILL=ARGS(6)

  IF T < 1 THEN T = 1
  IF R-T+1 > 0 THEN RIN=R-T+1 ELSE RIN=0

  FOR Y = -R TO R
    XOUT = INT(SQRT#(FLOAT#(R*R - Y*Y)) + 0.5)
    IF FILL=1 THEN
      GOSUB HLINE, CX-XOUT, CY+Y, 2*XOUT+1, COL
    ELSE
      GOSUB DPXL, CX-XOUT, CY+Y, COL
      GOSUB DPXL, CX+XOUT, CY+Y, COL
    ENDIF

    IF NOT(FILL) AND RIN > 0 THEN
      IF ABS(Y) < RIN THEN
        XIN = INT(SQRT#(FLOAT#(RIN * RIN - Y*Y)) + 0.5)
      ENDIF
    ENDIF
  NEXT
RETURN

REM ---- ELLIPSE cx,cy,vD,hD,t,col,fill
LABEL ELLIPSE
  VAR CX,CY,HDIAM,VDIAM,T,COL,FILL
  VAR INNERRX,INNERRY
  VAR Y,XOUT,XIN,FRAC,RX,RY

  CX    = ARGS(1) : CY = ARGS(2)
  VDIAM = ARGS(3) : HDIAM = ARGS(4)
  T     = ARGS(5) : COL = ARGS(6)
  FILL  = ARGS(7)

  IF T < 1 THEN T = 1
  RX = HDIAM / 2
  RY = VDIAM / 2

  IF RX <= 0 OR RY <= 0 THEN RETURN

  IF RX - T + 1 > 0 THEN INNERRX = RX -T + 1 ELSE INNERRX = 0
  IF RY - T + 1 > 0 THEN INNERRY = RY -T + 1 ELSE INNERRY = 0

  FOR Y = -RY TO RY 
    FRAC# = 1.0 - FLOAT#(Y * Y) / FLOAT#(RY * RY)
    IF FRAC# < 0 THEN FRAC# = 0
    XOUT = INT(FLOAT#(RX) * SQRT#(FRAC#) + 0.5)
    
    IF FILL = 1 THEN
      GOSUB HLINE,CX-XOUT, CY+Y, 2*XOUT+1, COL
    ELSE
      IF INNERRX=0 OR INNERRY=0 THEN
	GOSUB DPXL, CX-XOUT, CY+Y, COL
	GOSUB DPXL, CX+XOUT, CY+y, COL
      ELSE
        FRAC# = 1.0 - FLOAT#(Y*Y)/FLOAT#(INNERRY*INNERRY)
        IF FRAC# < 0 THEN
          XIN = -1
        ELSE
          XIN = INT(FLOAT#(INNERRX) * SQRT#(FRAC#) + 0.5)
        ENDIF

        IF XIN < 0 THEN
          GOSUB HLINE, CX-XOUT, CY+Y, 2*XOUT+1, COL
        ELSEIF XOUT > XIN THEN
          GOSUB HLINE, CX-XOUT,  CY+Y, XOUT-XIN, COL
	  GOSUB HLINE, CX+XIN+1, CY+Y, XOUT-XIN, COL
	ENDIF
      ENDIF
    ENDIF
  NEXT

RETURN

REM --- DrawChar(px%, py%, ch$, fg%, bg%)
REM 一文字の描画
LABEL DCHR
  VAR PX,PY,CH,FG,BG
  VAR A,I,P,D
  VAR ROW,PIX
  VAR FGH,FGL,BGH,BGL
  VAR COL

  PX = ARGS(1) : PY = ARGS(2) : CH$ = ARGS$(3)
  FG = ARGS(4) : BG = ARGS(5)
  FGH = FG / 256 : FGL = FG % 256
  BGH = BG / 256 : BGL = BG % 256

  A = PEEK(CH) : IF A=0 THEN RETURN
  P = SYSTEM(103) + A * 8 : REM System font area
  I = 0
  FOR ROW = 0 TO 7
    D = PEEK(P)
    FOR PIX = 0 TO 7
      IF D AND $80 THEN
        POKE CBUF + I * 2, FGH : POKE CBUF + I * 2 + 1, FGL
      ELSE
        POKE CBUF + I * 2, BGH : POKE CBUF + I * 2 + 1, BGL
      ENDIF
      D=D<<1 : I=I+1
    NEXT
    P=P+1
  NEXT
  GOSUB SAWIN, PX, PY, PX + 7, PY + 7
  GOSUB SCMD, $2C
  GOSUB SDBLK, CBUF, 8*2*8
RETURN

REM --- DrawString(px%, py%, txt$, fg%, bg%)
LABEL DSTR
  VAR PX,PY,TXT,FG,BG
  VAR K

  PX=ARGS(1) : PY=ARGS(2) : TXT$=ARGS$(3)
  FG=ARGS(4) : BG=ARGS(5)
  FOR K=0 TO LEN(TXT$)-1
    GOSUB DCHR, PX, PY, TXT$(K, 1), FG, BG
    PX = PX + 8
  NEXT
RETURN

REM --------------------------------
LABEL CLSC
  VAR COL,I,Y

  COL = ARGS(1)
  FOR I = 0 TO 239
    POKE BUF + I * 2,     COL / 256
    POKE BUF + I * 2 + 1, COL % 256
  NEXT
  GOSUB SAWIN, 0, 0, 239, 319
  FOR Y = 0 TO 319
    GOSUB SDBLK, BUF, 480
  NEXT
RETURN

上記プログラムの実行結果です。

IMG_2482.JPG

さいごに

ST7789を使った液晶ディスプレイに文字列、図形を表示できるようになりました。次のステップとしてクラスファイルにして汎用的に使えるように試しましたが何も描画されない状態で手詰まり状態です。何とかクラス化して使用できるようにしたいと思っています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?