DevTerm:感熱プリンタ

DevTermの感熱プリンタを使ってみました。

アプリやブラウザからは普通に使えますね。

コマンドラインやスクリプトから印刷するには、出力したい文字列を /tmp/DEVTERM_PRINTER_IN に渡せばよいみたいです。

#!/bin/bash
while :
do
read -n 1 KEY
echo "$KEY" > /tmp/DEVTERM_PRINTER_IN
done


せっかくなので、エミュレータからも印刷したいところです。直接プリンタにデータを送り込む方法が思いつかなかったのですが、エミュレータ側の機能としてプリンタ出力時に出力内容をテキストファイルに書き出す処理を持っていましたので、それを改造してファイルクローズ時に書き出されたファイルを /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);
        }
    }
}

横幅で自動改行されるので長いリストも問題なく印刷できます。
印刷にはプリンタ側で持ってるフォントが使われるので、プリンタ側の制御プログラムを入れ替えないと、/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

エミュレータから出力!

すばらしい。

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("")

 

カナのコードは、X1とFM-7で同じなので、FM-7のカナ混じりリストも印刷できました!(絵記号は異なってますけれど…。)

プリンタのプログラムビルドには 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」をイメージ印刷してみます。


出ますね…!上記の出力内容をバイナリファイルで作成しておいて、

cat 20220209test.dat > /tmp/DEVTERM_PRINTER_IN

で出力可能です。

サイズが違うとか、データが足りないとかみたいにパラメータを間違えると…

このありさま。パラメータ指定を探る試行錯誤で結構ムダ出力をしてしまったのだった。


エミュレータ側に内蔵フォントを用いて印刷をイメージ出力する機能がありますので、このイメージをプリンタ出力してみました。
出力イメージが大きい場合は、384×192 サイズに分割して、ファイル出力&印刷を繰り返します。テキスト出力の時は、折り返し処理を自動的にやってくれてたのですが、イメージ出力だとイメージ作成時に幅を指定して折り返ししてあげる必要がありました。


いい感じ!


これで、どのエミュレータでもそれぞれのフォントで印刷可能…!と思ったのですが、エミュレータ側でイメージ印刷が可能なのは現状では MZ-80Kエミュレータだけみたいでした。残念。X1エミュレータだと、一部イメージ印刷&一部プリンタフォント印刷みたいな混合でした。これはちょっと仕組み的に移植が難しいですね。

であれば、やはりプリンタ側のフォントを(エミュレータ起動タイミングなどで)入れ替えるのが一番良さそうです。プリンタ制御プログラムにフォントイメージを動的に送れるようなコマンドがあればいいのにな。プリンタプログラムにそういう仕組みを自分で追加してしまうのもアリですね。