---
title: 陳大的 ming.py 試玩筆記
image: https://i.imgur.com/09UWy9m.png
---
# 陳大的 `ming.py` 試玩筆記
###### tags: `字庫` `MicroPython` `ESP32`
> [color=#58f][name=Paoyung][time=Jun 05, 2022] [:snake: ℳ𝒾𝒸𝓇ℴ𝒫𝓎𝓉𝒽ℴ𝓃 隨手記](/@PaoyungChang/mpy_trifiles)
> [color=green] <span class="c_maroon">相關主題 👉 [微控制器上字庫的選擇](/@PaoyungChang/fonts_selection)</span>
寫在前面
---
因為陳大昨日(2022/06/05)的線上同學會來不及上線,因此這個明體中文字庫正確用法還沒公佈,或許已經有配套的工具和套件了。而我礙於**撿到寶**心急先做了一番測試。待陳大下週講解教學後,如有需要我再把一些內容記錄出來。也想要試試的人可以到 LINE 群組或[共學筆記](/@LHB-0222/2022micropython)中尋找 `ming.py` 這個檔回來玩玩。:relaxed:
u8g2顯示中文
---
一般在 MCU 上若沒有合適的工具或套件,想要顯示中文不能算是個簡單任務,在 Arduino 社群間的做法就是使用 u8g2,[益師父](https://www.facebook.com/groups/3636001276437792)已經做過許多的教學,不然[傑森創工](https://blog.jmaker.com.tw/chinese_oled/)也有詳細的解說,而[黑大](https://blog.darkthread.net/blog/u8g2-cht-font-tool/)還寫了自動化工具。
字庫IC
---
之前曾提過我其實並不熟悉 Arduino IDE 的生態圈,反而喜歡在非 C/C++ 的語言間遊走,最常用的是 MicroPython 和 [Espruino](https://www.espruino.com),在某次為了 [Espruino](https://www.espruino.com) 而購買 STM32F103RCT6 開發板時,賣家說開發板上的 W25 帶有字庫,然後從賣家給的文件發現那顆 Flash 其實是 Clone 了 [GT30L24T3Y](http://www.hobos.com.cn/upload/datasheet/GT30L24T3Y.pdf) 這顆字庫 IC,因為它包含了不同大小的字型、以及繁體和簡體,可用 GB2312、GB12345、Big5 和 Unicode 來取碼,所以取字過程有點小複雜,不過使用它就不需要事先取字,隨時可以從它讀取出來,且[這顆 IC 還非常的便宜](https://item.taobao.com/item.htm?spm=a230r.1.14.8.71a9e28648M3c5&id=40161054630&ns=1&abbucket=17),想說需要時掛上即可,因此就沒再找別的方案。
> [color=orange]
> - 順道一提: ESP32 上的 4MB 也是來自於 W25
> - [GT30L24T3Y 文件](http://www.hobos.com.cn/upload/datasheet/GT30L24T3Y.pdf)
> - [GT30L24T3Y 價格](https://item.taobao.com/item.htm?spm=a230r.1.14.8.71a9e28648M3c5&id=40161054630&ns=1&abbucket=17)
 
陳大的明體中文字庫
---
而前幾天在 LINE 群組 [益師父 MicroPython 同學會](https://www.facebook.com/groups/3636001276437792) 的討論中,陳大放出一個 `ming.py` 明體中文字庫模組,和字庫奮鬥過的人一看到這個簡直是挖到寶了,以下就來探索一下它的內容。

它是一個有點大的 Python dictionary (28922 items),初步觀察 key 值應該與內碼相關。首先來觀察第1筆,key '0x0020' 的內容是一整排的 0x00,以 bitmap 的觀點來看它就是個空白,而 ASCII 的 0x20 即是空白,這點是契合的。
```python=
>>> chr(int('0x0020'))
' '
>>>
```
思路驗證
---
照這個邏輯,key '0x0031' 不就該是 ASCII 的 1 嘛!要驗證這想法沒錯,就把數字 1 和英文的大寫 I、小寫 l 和符號 | 都取出來比對一下,若長得都有幾分像就代表思考的方向是正確的。
先找出對應的值:
```python=
>>> hex(ord('1'))
'0x31'
>>> hex(ord('I'))
'0x49'
>>> hex(ord('l'))
'0x6c'
>>> hex(ord('|'))
'0x7c'
>>>
```
<style>
.sz_code {
font-size: 11pt;
margin: 5px;
}
</style>
<div class="sz_code">
搜尋結果:<br>'0x0031': (0x00,0x00,0x10,0x18,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,),<br>
'0x0049': (0x00,0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,),<br>
'0x006c': (0x00,0x00,0x18,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,),<br>
'0x007c': (0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,),
</div>
以 bitmap 的觀點來看,中間段都是一個點連通的,所以方向正確,繼續 Go :rocket:
Unicode
---
再則中文應該都是以 unicode 來表示,而 key '0x0031'、'0x6211'...這樣來取中文字有點不順手,於是**我有個大膽的想法**,該不會 key 值就是 unicode 的值吧! 速速把 key 值前面的 '0x' 都換成 '\u' 來進行測試。
```python=
>>> print('\u0031', '\u0049', '\u006c', '\u007c')
1 I l |
>>> print('\u6211', '\u6709', '\u500b', '\u5927', '\u81bd', '\u7684', '\u60f3', '\u6cd5')
我 有 個 大 膽 的 想 法
```
沒錯,一旦的把 key 值換成了 unicode type,就可以用 chinese['中']、chinese['文'] 的方式來取字,這實在是太方便了。 :sunglasses:
> [color=orange]:loudspeaker: `ming.py` 對 MicroPython 來說檔案太大了,取字是用 Python 來操作。
```python=
Python 3.8.12 (default, Nov 26 2021, 23:35:35)
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from ming import chinese
>>> len(chinese)
28922
>>> # 有 28922 個字
>>> chinese['\u5bf6']
(0, 0, 4, 65, 252, 255, 4, 66, 250, 62, 32, 9, 248, 126, 32, 42, 252, 63, 16, 16, 240, 31, 16, 16, 240, 31, 16, 16, 240, 31, 28, 112)
>>> chinese['寶']
(0, 0, 4, 65, 252, 255, 4, 66, 250, 62, 32, 9, 248, 126, 32, 42, 252, 63, 16, 16, 240, 31, 16, 16, 240, 31, 16, 16, 240, 31, 28, 112)
>>> chinese['\u5bf6'] == chinese['寶']
True
>>> #取出內容相符
```
> [color=orange]:bulb: 用 unicode 格式或直接輸入中文都是可以的。
中文取字
---
整個字檔有 [28922](https://hackmd.io/@PaoyungChang/ryo-cPiuq) 個字,標準做法就是把需要的字取出另存檔案,再提供給微處理器使用,而取字用 Python 來做很輕鬆,不出幾行即可完成,日後寫成 function 就只要指定字串和檔名就完工了。
```python=14
>>> # 把會用到的字先列進來
>>> word_list = '我有個大膽的想法MicroPython同學會'
>>> words = {}
>>> for each in word_list:
... words[each] = chinese[each]
...
>>> # 檢查看看
>>> words
{'我': (0, 0, 0, 12, 224, 36, 60, '...'), ('balah balah...太長了..省略...')}
>>> # 寫成檔案
>>> with open('myfont.py', 'w') as f:
... f.write('words=')
... f.write(str(words))
...
6
2109
>>>
```
而這個產生出來的 `myfont.py` 直接上傳到 MicroPython 就可供 import 來調用,字數如果較多可以再把 .py 編為 .mpy,其大小能再大幅縮減,若是以 bytes 來存,縮小的範圍會更大,在此先暫不細說,以下的檔案功能和效果是一樣的,但大小差了將近三倍。
```
(mpfs) ➜ MicroPythonChsFont ls -al myfont*.*
-rw-r--r-- 1 oholiab oholiab 739 6月 6 15:21 myfont_c.mpy
-rw-r--r-- 1 oholiab oholiab 1710 6月 6 15:15 myfont_c.py
-rw-r--r-- 1 oholiab oholiab 1093 6月 6 15:19 myfont.mpy
-rw-r--r-- 1 oholiab oholiab 2137 6月 6 12:48 myfont.py
(mpfs) ➜ MicroPythonChsFont
```
舉個粟子
---
```python=
>>> # 這是 MicroPython
>>> # import 先前取出的字檔 myfont, 我們存成名為 words 的 dict
>>> from myfont import words
>>> # 取得 SSD1306 device
>>> disp = get_display()
>>> # 轉換成 list
>>> buf1 = [words[each] for each in 'MicroPy同學會']
>>> buf2 = [words[each] for each in '我有個大膽的想法']
>>> writeFont(disp, buf1, 12, 10)
116
>>> writeFont(disp, buf2, 0, 30)
128
>>> show(disp)
>>>
```

打完收工。:coffee:
如果你想知道陳大的檔案裡有哪些字,[請點這裡!](https://drive.google.com/file/d/16Ho05rihDH_ce61n79ZNpX14gQ_8b3Je/view?usp=sharing)
> [color=orangered][name=Paoyung Chang][time=Sat, Jun 11, 2022 11:49 PM]:loudspeaker: [續篇] [陳大的 ming.py 試完筆記](/@PaoyungChang/r12pLe6u9)
{%hackmd /@PaoyungChang/css_01 %}
{%hackmd /@PaoyungChang/intro_v0702 %}