電子回路系のナレッジを集約しています。主に自分用です。

Raspberry Pi Pico + microPythonでST7789を制御する

外部ライブラリを使うことなく、microPythonでST7789を制御してカラー液晶に表示できたので、メモ。

 

使用したのはこちらの安価なIPSカラー液晶ディスプレイ。

https://www.amazon.co.jp/gp/product/B07SZC2PSP/

 

ソースは以下の通り。

動作内容は、初期化で全域赤で塗りつぶしてから、ランダムな位置に白点を打っていくというもの。4096色モードを使用している。

 

# --------------------------------------------
# Raspberry Pi Pico + microPython IPS液晶
# 2022.3
# --------------------------------------------

from machine import Pin, SPI
import utime
import random
import struct

#---- ピンの定義

led = Pin(25, Pin.OUT)

#---- SPIの定義 IPS液晶

dc_ips = Pin(4, mode=Pin.OUT, value=1)
spi_ips = SPI(0, baudrate=50000000, polarity=1, phase=1, bits=8, firstbit=SPI.MSB, sck=Pin(2), mosi=Pin(3), miso=Pin(0))
print(spi_ips)

#---- グローバル変数

led_count = 0       # LED点滅制御用

#---- LED点滅制御

def control_led_blink():
    global led_count
    
    if led_count == 100:
        led_count = 0
    else:
        led_count += 1

    led.value(1 if led_count < 50 else 0)

#---- IPS初期化

def spi_ips_write_cmd(cmd):
    dc_ips.value(0)
    spi_ips.write(cmd)

def spi_ips_write_data(data):
    dc_ips.value(1)
    spi_ips.write(data)

def init_ips():
    # リセット
    spi_ips_write_cmd(b"\x01")
    utime.sleep_ms(150)

    # スリープOUT
    spi_ips_write_cmd(b"\x11")
    utime.sleep_ms(100)

    # カラーモード=4096色
    spi_ips_write_cmd(b"\x3A")
    spi_ips_write_data(b"\x33")
    utime.sleep_ms(100)

    # メモリデータアクセス制御=RGB
    spi_ips_write_cmd(b"\x36")
    spi_ips_write_data(b"\x00")
    utime.sleep_ms(100)

    # カラムアドレス=先頭
    spi_ips_write_cmd(b"\x2A")
    spi_ips_write_data(b"\x00\x00")
    spi_ips_write_data(b"\x01\x00")
    utime.sleep_ms(100)

    # ロウアドレス=先頭
    spi_ips_write_cmd(b"\x2B")
    spi_ips_write_data(b"\x00\x00")
    spi_ips_write_data(b"\x01\x00")
    utime.sleep_ms(100)

    # ディスプレイ表示反転=ON
    spi_ips_write_cmd(b"\x21")
    utime.sleep_ms(100)

    # 全域を赤で塗りつぶす
    spi_ips_write_cmd(b"\x2C")
    i = 0
    while i < 32768:
        spi_ips_write_data(b"\xf0\x0f\x00")
        i += 1

    utime.sleep_ms(100)

    # パーシャルOFF
    spi_ips_write_cmd(b"\x13")
    utime.sleep_ms(100)

    # 表示ON
    spi_ips_write_cmd(b"\x29")
    utime.sleep_ms(100)


#---- 起動ウェイト

utime.sleep_ms(200)

#---- IPS初期化

init_ips()

#---- メインループ

while True:
    utime.sleep_ms(10)

    # 10ms周期
    control_led_blink() # 10ms毎にLEDブリンク制御
    
    # ランダム座標を生成する
    x = random.randrange(239)
    y = random.randrange(239)
    xbytes = struct.pack(">H", x)
    ybytes = struct.pack(">H", y)
    
    # ロウにX座標をセット
    spi_ips_write_cmd(b"\x2A")
    spi_ips_write_data(xbytes)
    spi_ips_write_data(xbytes)

    # カラムにY座標をセット
    spi_ips_write_cmd(b"\x2B")
    spi_ips_write_data(ybytes)
    spi_ips_write_data(ybytes)

    # フレームメモリにデータをライト(白)
    spi_ips_write_cmd(b"\x2C")
    spi_ips_write_data(b"\xFF\xFF\xFF")

f:id:sin-elec-tech:20220325011217j:plain



 

VivadoのシミュレーションでVRFC 10-2063エラーが発生して実行できない

古くからあるVivadoのバグです。

多くのファイルを手で修正する必要があります。テストベンチを作り直しても、このバグは解消しません。

axi_iicドキュメントの誤記

scl_t、sda_tの初期値が0x0となっているが、シミュレーションしてみると初期値としてHighレベルが出てくる。IOBUFのTはHighでゲート閉/Input、Lowでゲート開/Outputであり、初期値が0x0でゲート開/ドライブ状態となるのはおかしい。0x1が正しいと思われ、ドキュメントは間違っているようだ。

f:id:sin-elec-tech:20210328130745p:plain

 

XILINXのIOBUFの3-stateゲート信号TはActive-Lowである

XILINXのドキュメントにはActive Highと記載されており、図にも負論理を示す○はついていないが、実際は負論理である。

 

参考:

www.reddit.com

 

追記:

ドキュメントによっては High:Input Low:Output というのが書いてあるので、TはTであってGateではないのだと言うことかもしれない。だがTとは何の略なのか。DirectionでDとかならわかるけど。

FPGAの回路内でHi-Zになるようなゲートは使わない

FPGA/CPLDでは、チップ内にHi-Zを作らないようにすべきである。絶対使っちゃいけないってことはないが、動作速度の面で不利になる。また、FPGA内の回路リソースの使い方としてはちょっともったいない。

 

ふつう、FPGAのロジック・エレメントには、トライステートのゲートはついていない。ゲートがあるのはIOブロックだけである。したがって、トライステートを記述すると、IOブロックを使用することになる。LEからIOBまで配線が伸びることになるので、配線遅延が発生する。また、LEより数がずっと少ないIOBリソースを消費するので、ちょっともったいない感がある。