Home

Awesome

從 GT30L24T3Y/ER3303-1 SPI 字庫芯片讀取 BIG-5 漢字的簡易 MicroPython 驅動程式

IMG_0001

GT30L24T3Y 又名 ER3303-1 是高通 (Genitop,不是那個 Qualcomm) 生產的眾多字庫晶片之一,如今還可以買到,但網路上找不到什麼操作範例,原始文件也寫得不是很清楚。花了一番功夫,總算搞懂是怎麼運作的了。

0117021043

使用

big5.py 內的 getBig5Font 函式拷貝到你的程式中即可。其呼叫參數如下:

getBig5Font(spi, cs, font_code, font_size, raw=False, printout=False)
參數意義
spiSPI 物件 (machine.SPI 或 machine.SoftSPI)
csCS 腳位物件 (machine.Pin)
font_codeBIG-5 字碼 (字串或數值, 如 'A140' 或 0xA140, 參閱字碼表)
font_sizeBIG-5 字體大小 (12, 16 或 24)
raw設為 True 時直接傳回 bytes 陣列, 否則預設傳回 framebuf.FrameBuffer
printout設為 True 時會在 REPL 印出該字的文字圖檔

傳入不正確的 font_code 或 font_size 引數會使它拋出錯誤。SPI 物件的最高 baudrate 只能設為 40 MHz;儘管官方文件指出 GT30L24T3Y 通訊速度可達 80 MHz,但測試上無法這樣穩定運作。

預設下此函式會傳回 MicroPython 的 FrameBuffer 物件,讓你能把它直接貼在某些顯示器模組上。據我所知 SSD1306 OLEDPCD8544/Nokia 5110 LCD 的驅動程式都會使用 FrameBuffer。

如果你要使用純 bytes 陣列,ER3303-1 手冊的 12-13 頁有說明字型資料是如何排列的。

BIG-5 字體

GT30L24T3Y 支援 GB、BIG-5 和 Unicode 三種中文字,以及幾種 ASCII 英數字形。目前我只實作 BIG-5。MicroPython 本身已經提供 8x8 英數字體,BIG-5 本身也有數字和符號等等,所以 ASCII 的部分儘管查詢上更簡單,在此仍比較沒有使用的需要。

GT30L24T3Y 將漢字字庫的索引資料一併存在晶片中,所以查詢時其實要做兩次 SPI 讀寫,第一次是用某字在字碼表的排列順序去查它在晶片裡的 offset,第二次才是把字讀出來。問題就在於,這個已經有點歷史的晶片的 BIG-5 字碼和你在現代軟體得到的結果 (包括用正規 Python 的 codecs.encode()) 會有出入,有很多後面的非中文字並不存在於晶片中,所以還是乖乖用舊的字碼表吧。

可用的 BIG-5 字體有 12x12、16x16 及 24x24 像素三種尺寸 (正確來說是 11x12,15x16 與 24x24)。有趣的是 Unicode 字庫似乎跟 BIG-5 是共用的,只不過是改成讓你用 Unicode 字碼來查詢而已,但我並不清楚此晶片使用的 Unicode 編碼順序 (用 ord() 取得的字碼跟晶片用的似乎不太一樣)。另外就文件的說法,24x24 字體只支援基本中文字,所以字碼不能超過 E1BC。

測試

我在圖中用的是 Raspberry Pi Pico 與 SSD1306,但這應該也適用於 ESP8266/ESP32。我用的 MicroPython 版本為 v1.16。

1

GT30L24T3Y 接線 (使用 SPI0 硬體腳位):

腳位接線
GNDGND
3.3-5V3.3V
CSGPIO 17
SI (MOSI)GPIO 19
SO (MISO)GPIO 16
SCKGPIO 18

SSD1306 接線 (使用 I2C1 硬體腳位):

腳位接線
VCC3.3V
GNDGND
SCLGPIO 27
SDAGPIO 26

下面的範例會用不同大小印出一連串文字。你可以先在字碼表查詢你要使用的字,並建一個 Python 字典當對照表。不過由於 MicroPython 是基於 Python 3.4,走訪字典內容時不會照元素的存入順序印出,所以你仍得用另外的方式 (比如一個串列) 來走訪。

    # 前面貼上 getBig5Font() 函式

    # 字碼對照表    
    data = {
        '我': 'A7DA',
        '要': 'AD6E',
        '代': 'A54E',
        '替': 'B4C0',
        '月': 'A4EB',
        '亮': 'AB47',
        '懲': 'C367',
        '罰': 'BB40',
        '你': 'A741',
        }

    # 要顯示的文字
    text = '我要代替月亮懲罰你'

    from machine import Pin, I2C, SPI
    from ssd1306 import SSD1306_I2C  # https://github.com/stlehmann/micropython-ssd1306

    spi = SPI(0, baudrate=40000000, sck=Pin(18), mosi=Pin(19), miso=Pin(16))
    cs = Pin(17, Pin.OUT, value=1)
    
    display = SSD1306_I2C(128, 64, I2C(1, scl=Pin(27), sda=Pin(26)))
    display.fill(0)
    
    pos = 0
    for t in text:
        display.blit(getBig5Font(spi, cs, data[t], font_size=12), pos, 0)  # 印上文字
        pos += 12
    
    pos = 0
    for t in text:
        display.blit(getBig5Font(spi, cs, data[t], font_size=16), pos, 18)
        pos += 16
        
    pos = 0
    for t in text:
        display.blit(getBig5Font(spi, cs, data[t], font_size=24), pos, 40)
        pos += 24
    
    display.show()  # 顯示文字
    
    buf = getBig5Font(spi, cs, data['月'], font_size=24, raw=True, printout=True)
    print(buf)

最後兩行會在主控台印出

------------------------
------------------------
------------------------
#-----------------------
-#----------------------
-##---------------------
--###-------------------
---####################-
-----#################--
----------#-----#----#--
----------#-----#----#--
----------#-----#----#--
----------#-----#----#--
----------#-----#----#--
--#-------#-----#----#--
--#-------#-----#----#--
###-------#-----#----#--
-######################-
--#####################-
---------------------#--
------------------------
------------------------
------------------------
------------------------
b'\x00\x00\x00\x00\x00\x00\x00\xfe\xfc\x84\x84\x84\x84\x84\x84\x84\x84\xfe\xfe\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff        \xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x80@`8\x1f\x07\x00\x00\x00\x00\x00  \xe0\x7f?\x00\x00\x00\x00\x00'