Arduino - TV出力(TVoutLibrary使用)で漢字表示
前回、美咲フォントを使って日本語表示をやってみたのですが、さすがに8x8ドットは
フォントが潰れます。
そこで、作業ついでに以前作成した漢字フォントROMとライブラリを使って大き目の
フォント表示を試してみました。どれくらいのサイズがよろしいのかと..
関連記事
Arduino用美咲フォントライブラリを作成しました(2)
arduinoで利用可能な漢字フォントROMの製作
arduinoで利用可能な漢字フォントROMの製作(2)
表示の様子(動画)
画面キャプチャした画像
8x8ドットのフォント(美咲フォント)
10x10ドットのフォント1(naga10フォント)
12x12ドットのフォント(東雲フォント)
14x14ドットのフォント(東雲フォント)
16x16ドットのフォント(東雲フォント)
20x20ドットのフォント(kappa20フォント)
24x24ドットのフォント(jiskan24フォント)
情報量と見た目の兼ね合いで、10~14ドットが実用的でしょうかね。
20、24ドットは実用性無さそうでTVout用途としては削ても良いかも..
TVoutライブラリはお手軽に使えるのですが、SRAMメモリー不足に悩まされます。
多用する場合、文字列はフラッシュメモリに乗せないといけませんね。
SRAMが4倍のArduino Megaを使えば快適かもしれません。
回路的には次のような感じです。
漢字フォントを突っ込んでいるSPIフラッシュメモリ W25Q64が3.3V稼働のため、
レベルシフトのためにCD4050を使っています。
他のCMOS 4050(東芝製のTC4050など)でもいけるでしょう。
電源部の0.22μFのパスコン、正規品Arduinoまたは、品質の良い互換機では
多分不要です。手持ちの中華製格安Arduinoは入れないとSPI通信でデータ化けが
発生しました。3.3V生成周りがよろしくないようです。SainSmart製互換機では
無くても安定動作しました。
「安物Arduonoでもいけるやん」と使っていたのですが、やはり安い理由がありそうです。
スケッチ
// // TVOutでマルチフォント表示 by たま吉さん 2016/03/30 // #include <SPI.h> #include <W25Q64.h> #include <exfonts.h> #include <TVout.h> // TVoutの派生クラスの定義し、 // bitmapメソッドをフラッシュメモリではなく、SRAM対応させる class exTVout : public TVout { public: void bitmap(uint8_t x, uint8_t y, const uint8_t* bmp, uint16_t i, uint8_t width, uint8_t lines); }; // bitmapメソッド void exTVout::bitmap(uint8_t x, uint8_t y, const uint8_t* bmp, uint16_t i, uint8_t width, uint8_t lines) { uint8_t temp, lshift, rshift, save, xtra; uint16_t si = 0; rshift = x&7; lshift = 8-rshift; if ( width & 7 ) { xtra = width & 7; width = width / 8; width++; } else { xtra = 8; width = width/8; } for ( uint8_t l = 0; l < lines; l++ ) { si = (y + l)*display.hres + x/8; if (width == 1) temp = 0xff >> rshift + xtra; else temp = 0; save = screen[si]; screen[si] &= ((0xff << lshift) | temp); temp = *(bmp+ i++); screen[si++] |= temp >> rshift; for ( uint16_t b = i + width-1; i < b; i++ ) { save = screen[si]; screen[si] = temp << lshift; temp = *(bmp + i); screen[si++] |= temp >> rshift; } if ( rshift + xtra < 8 ) screen[si-1] |= (save & (0xff >> rshift + xtra)); if ( rshift + xtra - 8 > 0 ) screen[si] &= (0xff >> rshift + xtra - 8); screen[si] |= temp << lshift; } } exTVout TV; // TV出力オブジェクト exfonts ft; // フォント管理オブジェクト // 指定位置に1文字表示 void mputc(uint8_t x, uint8_t y, uint16_t code) { byte buf[MAXFONTLEN]; ft.getFontData(buf,code); // フォントデータの取得 TV.bitmap(x,y, buf ,0,ft.getWidth(), ft.getHeight()); } // 指定位置に文字列表示 void mprint(uint8_t x, uint8_t y, char* str) { uint16_t wstr[64]; int8_t len; len = exfonts::Utf8ToUtf16(wstr, str); // UTF8からUTF16に変換する for (uint8_t i=0; i <len; i++) { mputc(x, y, wstr[i]); if (x + ft.getWidth()*2 < 120) { x += ft.getWidth(); } else { x = 0; if (y+ft.getHeight()*2 < 80) { y+=ft.getHeight(); } else { break; } } } } void setup () { ft.init(); // フォント管理の初期化 TV.begin(NTSC, 120, 80); // TVOut開始 //7種類のフォントサイズで文字列表示 while(1) for (uint8_t i =0 ; i <7; i++) { TV.fill(0); ft.setFontSize(i); mprint(0,0,"春はるはあけぼのやうやう白くなりゆく山際、少し明かりて、紫だちたる雲の細くたなびきたる"); delay(1000*10); } } void loop () { }
プログラム的には、TVoutからの派生クラスexTVoutを作成してbitmapメソッドを再定義しています。
TVoutライブラリのフォントを表示を行うbitmapメソッドがフラッシュメモリ上のフォント
データにしか対応していないためです。基本クラスのbitmapメソッドをコピペして、
SRAM上の領域を参照するよう、修正しました。
こういった差分プログラミング、C++を使う利点ですね。
フォント周りは自作のライブラリexfontを使っています。
画面出力のサイズ指定をsetup()内の TV.begin(NTSC, 120, 80) で行っているのですが、
縦を90から80へとちょっとだけ小さくしてメモリ消費を抑えました。
これで150バイト消費を抑えられます。これをしないと画面にごみが表示されます。
多分、メモリ不足です。
Arduinoがあと2kバイト多くRAMがあればTVoutで色々と出来そうなのですが、
メモリ不足でシリアル通信等が出来ません。
一方、プログラム領域の利用は7,842バイトとまだ24kバイトも余っています。
最近のコメント