DevTermの感熱プリンタを使ってみました。
アプリやブラウザからは普通に使えますね。
DevTerm 感熱プリンタ初印刷! pic.twitter.com/0IapR9rizZ
— Nochi (@shikarunochi) January 10, 2022
Hal(@Hal_clockwork) さんのアドバイスで、GIMP でサイズ調整 & 2値化することで、かなりキレイになりました! pic.twitter.com/ISscgJuVim
— Nochi (@shikarunochi) January 10, 2022
コマンドラインやスクリプトから印刷するには、出力したい文字列を /tmp/DEVTERM_PRINTER_IN に渡せばよいみたいです。
#!/bin/bash while : do read -n 1 KEY echo "$KEY" > /tmp/DEVTERM_PRINTER_IN done
DevTerm でタイプライターごっこ。
1文字ずつ改行されてしまいますけれどw pic.twitter.com/AKFwz2LavT— Nochi (@shikarunochi) January 18, 2022
せっかくなので、エミュレータからも印刷したいところです。直接プリンタにデータを送り込む方法が思いつかなかったのですが、エミュレータ側の機能としてプリンタ出力時に出力内容をテキストファイルに書き出す処理を持っていましたので、それを改造してファイルクローズ時に書き出されたファイルを /tmp/DEVTERM_PRINTER_IN に送るように実装してみました。
//prnfile.cpp void PRNFILE::close_file() { if(fio->IsOpened()) { // remove if the file size is less than 2 bytes bool remove = (fio->Ftell() < 2); fio->Fputc('\n'); fio->Fclose(); if(remove) { FILEIO::RemoveFile(file_path); }else{ char command[_MAX_PATH + 256]; sprintf(command, "cat %s > /tmp/DEVTERM_PRINTER_IN", file_path); printf("%s\n",command); int ret = system(command); FILEIO::RemoveFile(file_path); } } }
DevTerm、MZ-80K エミュレータからのプリンタ出力できました!
BASICプログラムリストも印刷できますー。記号は化けてしまいますけれど。 pic.twitter.com/a28wDU9rNY— Nochi (@shikarunochi) February 6, 2022
FM-7 で LLIST pic.twitter.com/vGoDaH3r72
— Nochi (@shikarunochi) February 6, 2022
プリンタ「カタカタカタ…」 pic.twitter.com/44c9MnFaqR
— Nochi (@shikarunochi) February 6, 2022
横幅で自動改行されるので長いリストも問題なく印刷できます。
印刷にはプリンタ側で持ってるフォントが使われるので、プリンタ側の制御プログラムを入れ替えないと、/tmp/DEVTERM_PRINTER_IN を使って絵記号やカナを印刷することはできないです。
プリンタプログラムのソースは公式 GitHub で公開されていますので、プリンタ側の制御プログラムを入れ替えてみました!
DevTerm/Code/thermal_printer/
https://github.com/clockworkpi/DevTerm/tree/main/Code/thermal_printer
ビルド方法と、プリンタ制御プログラム入れ替え方法も書いてありました。入れ替え前の devterm_thermal_printer.elf は、バックアップ取っておきましょう。
MZ-80K独自の絵記号やカナを印刷するため、MZ-80Kフォント追加してビルドしてみます。
Python スクリプトで、MZ-80KフォントのROMファイルを C の配列に変換します。(ディスプレイコードの変換もあるので変換テーブル用意しました。)
変換したデータの使い方は、既存のフォントファイル pcf_5x7-ISO8859-1_5x7.h などを参考にしてください。
#convertMZ80Font.py ascii2disp = [ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6b,0x6a,0x2f,0x2a,0x2e,0x2d, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x4f,0x2c,0x51,0x2b,0x57,0x49, 0x55,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x52,0x59,0x54,0x50,0x40, 0xc7,0xc8,0xc9,0xca,0xcb,0xcd,0xce,0xcf,0xdf,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed, 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xc0, 0x80,0xbd,0x9d,0xb1,0xb5,0xba,0xb4,0x9e,0xb2,0xb6,0xb9,0xbe,0x9f,0xb3,0xb7,0xbb, 0xbf,0xa3,0x85,0xa4,0xa5,0xa6,0x94,0x87,0x88,0x9c,0x82,0x98,0x84,0x92,0x90,0x83, 0x91,0x81,0x9a,0x97,0x93,0x95,0x89,0xa1,0xaf,0x8b,0x86,0x96,0xa2,0xab,0xaa,0x8a, 0x8e,0xb0,0xab,0x8d,0xa7,0xa8,0xa9,0x8f,0x8c,0xae,0xac,0x9b,0xa0,0x99,0xbc,0xb8, 0x40,0x3b,0x3a,0x70,0x3c,0x31,0x5a,0x3d,0x43,0x56,0x3f,0x1e,0x4a,0x1c,0x5d,0x3e, 0x5c,0x1f,0x5f,0x5e,0x37,0x7b,0x7f,0x36,0x7a,0x7e,0x33,0x4b,0x4c,0x1d,0x6c,0x5b, 0x34,0x41,0x35,0x34,0x74,0x30,0x7c,0x75,0x7d,0x4d,0x6f,0x6e,0x32,0x77,0x76,0x72, 0x73,0x47,0x7c,0x53,0x71,0x4e,0x6d,0x48,0x46,0x3d,0x44,0x1b,0x58,0x79,0x42,0x60 ] fontFile = open("FONT.ROM", "rb") for asciiIndex in range(256): dispIndex = ascii2disp[asciiIndex] fontFile.seek(dispIndex * 8) print("\t// code=" + str(asciiIndex) + ", hex=" + hex(asciiIndex)) print("\t",end='') for x in range(8): print("0x" + fontFile.read(1).hex(),end=',') print("")
devterm_thermal_printer.c の void printer_set_font(CONFIG*cfg,uint8_t fnbits) に、使われてないフォント番号で追加。標準で4まで使われてたので5にしました。最大7までみたいです。(最初、80とか指定して切り替わらずに悩んでいたw)
フォントを切り替えて、
echo -en "\x1b\x21\x5" > /tmp/DEVTERM_PRINTER_IN
エミュレータから出力!
MZ-80K のフォントをプリンタ側のロジックに組み込んでみました!
コード変換間違って「アイエウオ」になってしまってますw pic.twitter.com/ebbBzShKZe— Nochi (@shikarunochi) February 7, 2022
「アイエウオ」も直しました! pic.twitter.com/TRYIrqztFx
— Nochi (@shikarunochi) February 7, 2022
すばらしい。
X1フォントも入れてみました。
同じように PythonスクリプトでフォントROMを変換。ディスプレイコードの変換は必要ないです。
#convertX1Font.py fontFile = open("FNT0808.X1", "rb") for asciiIndex in range(256): print("\t// code=" + str(asciiIndex) + ", hex=" + hex(asciiIndex)) print("\t",end='') for x in range(8): print("0x" + fontFile.read(1).hex(),end=',') print("")
FM-7 とカナコードが同じ X1 フォントにしてみました。バッチリだ!
フォントの形はX1フォントになりますけれどw
機種によって微妙な違いがあるのですよね。 pic.twitter.com/6NG8BtpwSa— Nochi (@shikarunochi) February 7, 2022
カナのコードは、X1とFM-7で同じなので、FM-7のカナ混じりリストも印刷できました!(絵記号は異なってますけれど…。)
FM-7 と X1、英数とカナは合ってるけど、カナより後が全然違いますねw
月火水木金土を入れるのはシャープのこだわりか。 pic.twitter.com/d5hi79bUha— Nochi (@shikarunochi) February 7, 2022
現在の半角カナコードを見ると、MZ-80C/K の方が異端なのですよね…。
CHR$(32)も、スペースか空文字かの違いがありますね。 pic.twitter.com/WkktRx7gwc— Nochi (@shikarunochi) February 7, 2022
プリンタのプログラムビルドには wiringPi.h と wiringPiSPI.h のヘッダが必要となります。wiringPi ライブラリ(/usr/lib/libwiringPi.so) は最初から入ってましたので、ヘッダさえあればビルド可能でした。
ここから取ってきて、/usr/local/include/ に入れておけばOKです。
WiringPi/wiringPi/
https://github.com/WiringPi/WiringPi/tree/master/wiringPi
DevTermのフォーラムを見てみますと、ソースを読んだ人が隠しコマンドを見つけていて、/tmp/DEVTERM_PRINTER_IN 経由でのイメージ印刷も可能とのこと!
Printing Images with /tmp/DEVTERM_PRINTER_IN
https://forum.clockworkpi.com/t/printing-images-with-tmp-devterm-printer-in/7650
イメージ印刷のコマンドは「GS(\x1d) v 0 p wL wH hL hH [Data]」で、一度に印刷できるのは 9224 byte。1byte で横 8ドットなので、73792 ドット。DevTermのプリンタは幅 384 ドットなので、幅最大で印刷すると 384*192ドットとなります。
ためしに、8×8 で「A」をイメージ印刷してみます。
DEVTERM_PRINTER_IN で イメージ印刷やってみました。8×8 で 「A」をドット印刷。データはこういう感じ。 https://t.co/2TofqRUHRT pic.twitter.com/7QC86CIeSb
— Nochi (@shikarunochi) February 9, 2022
コマンドは「GS(\x1d) v 0 p wL wH hL hH [Data]」
なので実際の入力はこうです。
echo -en “\x1d\x76\x30\x70\x01\x00\x08\x00\x38\x44\x82\xfe\x82\x82\x82\x00” > /tmp/DEVTERM_PRINTER_IN
おおっ、できました! pic.twitter.com/Srenoblp9L— Nochi (@shikarunochi) February 9, 2022
出ますね…!上記の出力内容をバイナリファイルで作成しておいて、
ということはこういうバイナリデータを作って、
cat 20220209test.dat > /tmp/DEVTERM_PRINTER_IN
でOK!なるほど…! pic.twitter.com/CKpJj7jxZT— Nochi (@shikarunochi) February 9, 2022
cat 20220209test.dat > /tmp/DEVTERM_PRINTER_IN
で出力可能です。
サイズが違うとか、データが足りないとかみたいにパラメータを間違えると…
パラメータ間違うと、こんななっちゃいます。 pic.twitter.com/OCdaHflrvk
— Nochi (@shikarunochi) February 9, 2022
このありさま。パラメータ指定を探る試行錯誤で結構ムダ出力をしてしまったのだった。
エミュレータ側に内蔵フォントを用いて印刷をイメージ出力する機能がありますので、このイメージをプリンタ出力してみました。
出力イメージが大きい場合は、384×192 サイズに分割して、ファイル出力&印刷を繰り返します。テキスト出力の時は、折り返し処理を自動的にやってくれてたのですが、イメージ出力だとイメージ作成時に幅を指定して折り返ししてあげる必要がありました。
折り返しがキッチリできれば、大きめフォントで問題ないですね。 pic.twitter.com/eU8QD64qIx
— Nochi (@shikarunochi) February 9, 2022
プログラムリストもOK! pic.twitter.com/BlD501MPnT
— Nochi (@shikarunochi) February 9, 2022
いい感じ!
これで、どのエミュレータでもそれぞれのフォントで印刷可能…!と思ったのですが、エミュレータ側でイメージ印刷が可能なのは現状では MZ-80Kエミュレータだけみたいでした。残念。X1エミュレータだと、一部イメージ印刷&一部プリンタフォント印刷みたいな混合でした。これはちょっと仕組み的に移植が難しいですね。
であれば、やはりプリンタ側のフォントを(エミュレータ起動タイミングなどで)入れ替えるのが一番良さそうです。プリンタ制御プログラムにフォントイメージを動的に送れるようなコマンドがあればいいのにな。プリンタプログラムにそういう仕組みを自分で追加してしまうのもアリですね。