--- 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) ![](https://i.imgur.com/rzbIAZB.png) ![](https://i.imgur.com/ZxQSg1U.png) 陳大的明體中文字庫 --- 而前幾天在 LINE 群組 [益師父 MicroPython 同學會](https://www.facebook.com/groups/3636001276437792) 的討論中,陳大放出一個 `ming.py` 明體中文字庫模組,和字庫奮鬥過的人一看到這個簡直是挖到寶了,以下就來探索一下它的內容。 ![](https://i.imgur.com/09UWy9m.png) 它是一個有點大的 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) >>> ``` ![](https://i.imgur.com/npSLczR.png) 打完收工。: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 %}