https://github.com/Tamakichi/pico_MicroPython_misakifont からcodeボタン→Download ZIPでダウンロードした後、 misakifontフォルダをCIRCUITPYドライブのlibにコピーした後、 sample_misaki.pyをSSD1302に表示させるため以下のようにちょこっと修正して、 from misakifont import MisakiFont import busio import adafruit_ssd1306 from board import * i2c = busio.I2C(GP15, GP14) display = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3C) display.fill(0) # 表示内容消去 """ フォントのビットマップ表示 """ def show_bitmap(x,y,fd): for row in range(0,7): for col in range(0,7): display.pixel(x+col,y+row,1 if (0x80>>col) & fd[row] else 0) str="こんにちは世界!" mf = MisakiFont() i=0 for c in str: d = mf.font(ord(c)) show_bitmap(10+i,30,d) i+=8 display.show() 表示させるとこんな感じ。 フォントの大きさの自由度はあまりないけど、これでいいんじゃないかな?
2025年2月23日日曜日
Raspberry Pi Picoに接続したSSD1302に美咲フォントで表示
raspberry pi picoでSSD1302に日本語を表示させてみた。
raspberry pi picoでSSD1302に漢字を表示させたい。 というわけで以下の順でやってみた。 1.フォントを探す 2.イメージのバイナリデータをファイル化 3.漢字コードからバイナリファイルの場所を算出するインデックスを作成 4.文字コード変換1(ShiftJIS→JIS変換) 5.文字コード変換2(UTF16→ShiftJIS変換) 6.文字画像確認その1(コンソール出力) 7.文字画像確認その2(SSD1302への出力) 8.文字列を表示する。 1.フォントを探す https://www.mgo-tec.com/blog-entry-ssd1306-shinonome.html を見てみると東雲フォント というものがあるみたいなので、今回はこれを(shnmk16.bdf)を使ってみる。 2.イメージのバイナリデータをファイル化 どうせメモリ上にフォントイメージを載せられないので、一字毎イメージファイルを読むことにする。 バイナリデータは1文字32バイトで保存。 そのためのshnmk16.bdfからバイナリファイルを抽出するスクリプトを作って流してみる。 def readandwritefontsfile(): isImageArea=False code=0 image=b'' with open('shnmk16.bdf') as f: with open('fontImage.bin','wb') as wf: for str in f: if str[:9]=="STARTCHAR" : code=int(str[10:14],16) elif str[:6]=="BITMAP" : image=b'' isImageArea=True elif str[:7]=="ENDCHAR" : wf.write(image) isImageArea=False elif isImageArea: image+=bytes.fromhex(str[:4]) readandwritefontsfile() で作成されたfontImage.binのファイルサイズが、220,128バイト。 CircuitPyドライブには載せられるが、メモリ上にこのイメージを載せるのは容量的に少し不安がある。 なので、表示の都度このファイルから1文字ずつ読み出すことにする。 3.漢字コードからバイナリファイルの場所を算出するインデックスを作成 shnmk16.bdf内で定義しているコードはJISのよう。 最初の文字コード(10進数)8481からで、使われていない文字はそのコードを飛ばしていて、 フォントコードが飛び番になっている。 確認方法として、以下を実施 ・「shnmk16.bdf」をキーワードENCODINGでgrepし、 ・出てきた行をExcelに貼り付け、 ・区切り位置ウィザードで半角スペースを区切り ・E2セルに=D2-D1-1の計算式を入れ、E列末までコピーし、値貼り付けにより計算式を数値にして ・オートフィルタでE列として、マイナス値が1件を確認したのち、値0のもののみ表示し、表示された行を行削除し、 ・オートフィルタを解除して、F1セルに=E1、F2セルに=F1+E2の計算式を入れ、F2セルをF列末までコピーして ・D列(コード)、E列(飛び番)、F列(累積)を抽出して確認 確認したところ、以下のコード値で直前のコードから+1より大きい数字に飛んでいる。コード値と飛び番数は以下。 コード 飛び番 累積 8737 162 162 8762 11 173 8778 8 181 8796 11 192 8818 7 199 8830 4 203 9008 177 380 9025 7 387 9057 6 393 9249 166 559 9505 173 732 9761 170 902 9793 8 910 10017 200 1110 10065 15 1125 10273 175 1300 12321 2016 3316 12577 162 3478 12833 162 3640 13089 162 3802 13345 162 3964 13601 162 4126 13857 162 4288 14113 162 4450 14369 162 4612 14625 162 4774 14881 162 4936 15137 162 5098 15393 162 5260 15649 162 5422 15905 162 5584 16161 162 5746 16417 162 5908 16673 162 6070 16929 162 6232 17185 162 6394 17441 162 6556 17697 162 6718 17953 162 6880 18209 162 7042 18465 162 7204 18721 162 7366 18977 162 7528 19233 162 7690 19489 162 7852 19745 162 8014 20001 162 8176 20257 162 8338 20513 205 8543 20769 162 8705 21025 162 8867 21281 162 9029 21537 162 9191 21793 162 9353 22049 162 9515 22305 162 9677 22561 162 9839 22817 162 10001 23073 162 10163 23329 162 10325 23585 162 10487 23841 162 10649 24097 162 10811 24353 162 10973 24609 162 11135 24865 162 11297 25121 162 11459 25377 162 11621 25633 162 11783 25889 162 11945 26145 162 12107 26401 162 12269 26657 162 12431 26913 162 12593 27169 162 12755 27425 162 12917 27681 162 13079 27937 162 13241 28193 162 13403 28449 162 13565 28705 162 13727 28961 162 13889 29217 162 14051 29473 162 14213 29729 162 14375 これをもとに以下の関数で入力code(SJISコード)を、その値により補正値を変え、 最終的にイメージファイルの読み込みアドレスを算出する 具体的には、 ・G2セルに="elif code <"&D2&" :(Alt+Enter) code-="&E1 計算式を入れG列末までコピーして、 ・G列をコピーし、テキストエディタに貼り付け、正規表現置換で\r?\nを\r\nに置換。 あとは前後を整備して、以下の関数を作る。 def binfileindex(code): if code < 8737 : pass elif code <8762 : code-=162 elif code <8778 : code-=173 elif code <8796 : code-=181 elif code <8818 : code-=192 elif code <8830 : code-=199 elif code <9008 : code-=203 elif code <9025 : code-=380 elif code <9057 : code-=387 elif code <9249 : code-=393 elif code <9505 : code-=559 elif code <9761 : code-=732 elif code <9793 : code-=902 elif code <10017 : code-=910 elif code <10065 : code-=1110 elif code <10273 : code-=1125 elif code <12321 : code-=1300 elif code <12577 : code-=3316 elif code <12833 : code-=3478 elif code <13089 : code-=3640 elif code <13345 : code-=3802 elif code <13601 : code-=3964 elif code <13857 : code-=4126 elif code <14113 : code-=4288 elif code <14369 : code-=4450 elif code <14625 : code-=4612 elif code <14881 : code-=4774 elif code <15137 : code-=4936 elif code <15393 : code-=5098 elif code <15649 : code-=5260 elif code <15905 : code-=5422 elif code <16161 : code-=5584 elif code <16417 : code-=5746 elif code <16673 : code-=5908 elif code <16929 : code-=6070 elif code <17185 : code-=6232 elif code <17441 : code-=6394 elif code <17697 : code-=6556 elif code <17953 : code-=6718 elif code <18209 : code-=6880 elif code <18465 : code-=7042 elif code <18721 : code-=7204 elif code <18977 : code-=7366 elif code <19233 : code-=7528 elif code <19489 : code-=7690 elif code <19745 : code-=7852 elif code <20001 : code-=8014 elif code <20257 : code-=8176 elif code <20513 : code-=8338 elif code <20769 : code-=8543 elif code <21025 : code-=8705 elif code <21281 : code-=8867 elif code <21537 : code-=9029 elif code <21793 : code-=9191 elif code <22049 : code-=9353 elif code <22305 : code-=9515 elif code <22561 : code-=9677 elif code <22817 : code-=9839 elif code <23073 : code-=10001 elif code <23329 : code-=10163 elif code <23585 : code-=10325 elif code <23841 : code-=10487 elif code <24097 : code-=10649 elif code <24353 : code-=10811 elif code <24609 : code-=10973 elif code <24865 : code-=11135 elif code <25121 : code-=11297 elif code <25377 : code-=11459 elif code <25633 : code-=11621 elif code <25889 : code-=11783 elif code <26145 : code-=11945 elif code <26401 : code-=12107 elif code <26657 : code-=12269 elif code <26913 : code-=12431 elif code <27169 : code-=12593 elif code <27425 : code-=12755 elif code <27681 : code-=12917 elif code <27937 : code-=13079 elif code <28193 : code-=13241 elif code <28449 : code-=13403 elif code <28705 : code-=13565 elif code <28961 : code-=13727 elif code <29217 : code-=13889 elif code <29473 : code-=14051 elif code <29729 : code-=14213 else : code-=14375 return (code-8481)*32 d=binfileindex(29400) 4.文字コード変換1(ShiftJIS→JIS変換) pythonの標準でのJISコード変換は見つからなかったので、SJIS→JISの変換関数を作る。 def sjis2jis(indata): h_data=int.from_bytes(indata)>>8 l_data=int.from_bytes(indata) & 0xff if h_data<=0x9f : if l_data < 0x9f : h_data=(h_data<<1) - 0xe1 else : h_data=(h_data<<1) - 0xe0 else : if l_data < 0x9f : h_data =(h_data << 1 ) -0x161 else: h_data =(h_data << 1 ) -0x160 if l_data < 0x7f : l_data -= 0x1f elif l_data < 0x9f: l_data -=0x20 else: l_data -=0x7e return h_data << 8 | l_data 5.文字コード変換2(UTF16→ShiftJIS変換) circuitpythonでは、「'あ'.encode('shift_jis')」が使えずUTF-8で表示されてしまう。 なので自前で変換テーブルを作成する。元ネタとして、 https://ameblo.jp/fc2miha/entry-12876272336.html から、 https://drive.google.com/file/d/1dMNG8bcM58w7uHRdBbqsP2R1HGAU9K2z/view?usp=sharing で、UTF-8→SJISの変換テーブル(list.dat)をダウンロードして、 次のプログラムでutf8tosjis.binを作り、 import json def readandwriteconvfile(): flg_firstline=True dic=dict() with open('utf8tosjis.bin','wb') as wf: with open(r'C:\Users\whisk\Downloads\list.dat','r',encoding='utf-8') as f: for str in f: if flg_firstline : flg_firstline=False continue str_utf8code,str_sjiscode,_=str.split(',') wf.write(int(str_utf8code,16).to_bytes(3,byteorder='big')) wf.write(int(str_sjiscode,16).to_bytes(2,byteorder='big')) readandwriteconvfile() 出来上がったbinファイルをcircuitpyドライブ直下におく。 で、変換表を使ったutf8文字列→sjis文字列への変換関数を作る。 dic=dict() allbyte=b'' with open('utf8tosjis.bin','rb') as f: allbyte=f.read() def utf8str2sjisstr(utf8str): retval=b'' for utf8char in utf8str: utf8=utf8char.encode() i=0 while i>8 l_data=indata & 0xff if h_data<=0x9f : if l_data < 0x9f : h_data=(h_data<<1) - 0xe1 else : h_data=(h_data<<1) - 0xe0 else : if l_data < 0x9f : h_data =(h_data << 1 ) -0x161 else: h_data =(h_data << 1 ) -0x160 if l_data < 0x7f : l_data -= 0x1f elif l_data < 0x9f: l_data -=0x20 else: l_data -=0x7e return h_data << 8 | l_data str_mainte='メンテナンス中' putString(utf8str2sjisstr(str_mainte),28,8) 表示はこんな感じ。 ま、泥臭いし半角対応はできていないので、今回作ってみたものの使わないかな? 8x8の美咲フォントを使う方は、いろいろ整備されているみたいだし。
登録:
投稿 (Atom)