niszetの日記

アナログCMOS系雑用エンジニアが頑張る備忘録系日記

(R)revealjsパッケージをフォークしていじっている

まだうまく動かないことが多々あるが…。

本家の更新は望めないので自分で欲しいものは自分で作るということでforkして勝手にやることにした。

github.com

ひとまず同梱されているrevealjsを最新のモノに置き換え、ファイルパスを整理して、historyにtrue強制しているところをデフォルトtrueの引数も受けられるようにした。default.htmlはpandocのものを持ってきた。

TODO

default.htmlはreveljsパッケージの方でよしなにサイズを調整しているようなので、それを旧版から適当に持ってくる予定。

ほか、reveal.jsで受けられるオプションの類いはrevealjsの方でも受けられるようにする。要確認。

Codeまわりがうごかない。要確認。

revealjs.com

h2の外側のsectionにattributesが入るものは大丈夫だが、h2自体に持たせないといけなさそうな機能はfilterで選別が必要かもしれない。いずれにしてもmarkdownからhtmlに変換してえいやでやるためにはrevealjs側でいい感じに手当てしないと駄目そうという気配。

jsやcssの記述を追加して対応するとバージョンアップ時に何が起こるのかわからないので基本的にはしない。しかしlua filterもASTで表現していないモノには無力なので、最悪の場合はreveal.js Writer in Pandocをいじらないといけないかも。要検討。

ひとまず、いくつかの機能は思った通りに動いているので、次のプレゼンの時にでも使ってみることにする、という目標でゆるゆると整備していこう。

(R)revealjsパッケージが古い

CRANにあるものは4年前のリリースのもの。

まえがき

久々にPandocのことをやろうと思って。Pandocの変遷はissueを読むと大変なので、取り込まれたPRを見るか、release noteを追うのが良い。今回は後者。 最近はpatchがぽつぽつ出ているが、2.14になったところで大きな変化があったので頑張って読んで追いつくことにする。

R上でPandocのバージョン(rmarkdownパッケージが見ているPandocのバージョン)を確認するには以下の通りです。

> rmarkdown::pandoc_version()
[1]2.14.0.3’

現時点の最新にした。

revealjs

Rでhtmlスライド作る時にとても便利なパッケージ。だった。今も使えるのだが、CRANにあるのは2017年のものであり、その後更新がない。

cran.r-project.org

より正確にはGitHub上では更新はされている。しかし、本体?のreveal.jsのバージョンが上がっていない。

github.com

最新は4.1.2のようだ。Rの方は3.3.0.1のようである。とても古い。

github.com

Pandocは最新バージョンだけが真のPandocであるとばかりにその時点の最新の周囲環境に合わせてバンバン更新が入る。API changeも3つ4つ入っていた。 詳しいことは読んでください。

pandoc.org

Pandoc本体にもrevealjs出力向けのテンプレートが同梱されている。これが最新版では更新されている。どうやらfalseを指定したときに項目ごと抜けてしまうのをtemplateの方を修正してfalseの値を持って出力するように、という修正のようである(背景はよく知らないが)

github.com

と、このようにPandocは最新のreveal.jsのバージョンに合わせて更新をしていくので、Pandocの挙動が破壊的な変更を伴った場合にR側のrevealjsパッケージが対応できないと詰むんじゃないの?と思った次第。実際のところは知らんけど…。

修正は出来そう

Rの方はreveal.jsを同梱しているので、これを置き換え、参照するファイルをそこに向ければ良さそう。

また、ワークアラウンドとしてはPandoc同梱のテンプレートを使うという手がある。テンプレートを以下のようにして出力する。

pandoc -D revealjs > reveal.template

Rmdから出力する際、keep_md: trueをつけてmdファイルを作ったうえで、先のテンプレートを入力して使えばとりあえず出力は出来る。

pandoc -t revealjs input.md --template reveal.template -o output.html

デフォルトのテンプレートでは$revealjs-url$https://unpkg.com/reveal.js@^4/が入るようなので、テンプレートの該当箇所をあらかじめダウンロードしてきたreveal.jsのファイル一式が入ったディレクトリに全て置き換えればオフラインでも使用できるし、cssの修正も手元でできる(これを便利にしているのがrevealjsパッケージという認識)

…と、最小のチェックしかしていない半分妄想で書いた記事である。何か間違っているかもしれないので見つけたらご一報を。

この一連の作業は面倒くさいので、forkして自分のリポジトリにrevealjsパッケージを生やした方が楽だな、と思っているのでやってみようと思っています(やるとは言っていない)

本当はPandocをやる予定だったんだが…

追記

そうそう、rstudioがrevealjsパッケージに力を入れていないこと自体には特に不満がない…わけじゃないけど理由はわかるのでまぁしょうがないよねって感じで考えてます。 ただ、開発継続する意思がないのであれば、適当なタイミングでリポジトリごとフリーズしてその旨明記してもらった方が良いのではないかなと思いました。

スポンジボブをNetflixで見始めた。

英語で。

英会話学校で、主に雑談している最近ですが、スポンジボブを見た感想を英語で書いていこうぜっていうことになったので書いていきます。今日は個別の話に言及しないけど。既に4話見ているのでそれぞれ書くのか…要約と感想を…。

Recently, I watch SpongeBob on NetFlix. This note is my impression of them written by English for learning.

I watch these movie twice per episode. Firstly I watch in Japanese. Then, changed to English. I usualy add subitles by English for checking the words. I feel stories of SpongeBob is very crasy. But phrases and words which are used in this movie are not difficult (of course, this anime is for kids). But its speed is much higher than my English text book for business (this text book has a much high level, actually). Words used in this anime are not common in business English so I find a lot of new terms which I don't know. Especially, expranation of the actions of characters are written as [something] form. These words are actually not common for me.

For example,

rustling: さらさら音をたてること whistling: ぴーと鳴く clinking: ちりんちりん鳴る slurp: 音をたてながら口に吸いこむ smacking: ぴしゃりと打つこと sigh: 溜息をつく boing: びよーん

are new for me. So, even though animation for kids, I discover new things.

I will write impressions for every episode after I watched.

キャラクタLCD「PLCD1602」で Bad Apple!! をYouTubeに公開しました。

これで私もYouTuber(ちがう)

ということで、キャラクLCDを色々といじっていたら出来てしまった、Bad Apple!!、ツイートにも書いた通りでYouTubeの方にも公開しています。

www.youtube.com

Twitter、いつの間にか2分くらいの動画上げられるようになっててすごい。でも動画は3分40秒あるので、フルバージョンはそちらをご覧ください。 おそらくTwitterよりもYouTubeの方が(圧縮されない分)画質が良いはずで、より動きがなめらかになっていると思います。

これをやるための技術は今まで書いた、文字をスクロールさせる技術と地続きで、表示領域を規定し、そこにデータを適切なタイミングで送ればそのドットの変化がアニメーションしているように見える、ということです。

niszet.hatenablog.com

niszet.hatenablog.com

結局のところ、字形をあらわすドット列も画像を表すドット列も、捉え方次第、というそういう感じですかね?

右側の文字列はキャラクLCD本来の使い方で文字を表示しています。つまりプリセットの半角カナを呼び出して表示しています。左側の画像データのフレーム番号とあわせて歌詞データを管理しておけば同じタイミングで表示させられますよね、という。

というわけで、これを作るための技術は特殊なものは特になく、データも非圧縮でXIAOのSRAMに載せているだけです。難しいことをしないで短期間で(実働2日)作り上げるために、完成とは何か、そのために何が必要で何が不要かを選別して、無理なく作るというのも大事だな(やる気が持続しないからね…)と思った次第です。

技術的な説明を書かないのにだらだら文章続けても良くないので、一旦切ります。

面白そうだなと思った方、是非、チャレンジしてみてください。

キャラクタLCDで高速で文字列をスクロールする技術

まずは文字表示領域の話からはじめよう。

新章突入です。これまでの話を踏まえて書いていますので、よくわからんところあるな?という場合は前の章の1話からご覧ください(↓こちらから)

niszet.hatenablog.com

なんの話?

今回は、キャラクLCDで文字をスクロールさせる動画の第二弾、こちらのtweetに貼った動画の内容の解説です。

前回の動画、

と比べると、かなり高速でスクロールさせているのに文字が見えることが分かると思います(残像が気になりはじめる速度なので、ちょっと読みづらいですが)

では、はじめます。

ひとつひとつ見ていく

今回使用しているキャラクLCD、PLCD1602(クレイン電子)は16x2の文字表示領域を持つ液晶ですが、液晶(コントローラ)の表示モードを切り替えることで上下の文字表示領域をまとめて1つの文字表示領域として使うことが出来ます。

言葉だけだとわかりづらいので図で見ていきましょう。サンプルコードにあった図形の例を使うと、2列で表示する場合に次のように表示されている記号が、

f:id:niszet:20210420162523p:plain

次のように上下の表示領域を使うイメージです。

f:id:niszet:20210421185254p:plain

このように、各ドットが上下2マス使うように引き延ばされて表示されます。これはCGRAM(あるいはDDROM)に入っている字形データそのものには変更なく、このモードに入るとこのように引き延ばされて表示されます。なので、上下に連続しないように表示ということは出来なさそうです(データシートの内容完全に理解した!とまでは言えないので、あったらすみません)

字形が縦に伸ばされているのは動画の右側、niszet0の文字列を確認すると分かりやすいでしょう(スクロールしないので) 余談ですが、文字単位ならDDRAMにどの文字を表示するのかの指定を変えていけばいいので、niszet0の文字列もスクロールさせることは可能のはずです(未確認)

さらに余談ですが、この使い方ではカーソルが表示できませんでした。これはまたいつか書きましょうかね…。

ちなみに、1列表示にしたとき、2列表示のときに下段に表示されていた文字列は表示されなくなります。2列のデータが1列に引き延ばされるイメージで、もし液晶の表示領域が右にずーっとのびているものであれば、20文字目に出てくるのかなと思います。結局、ここにデータがあっても表示されないだけなので、適当な文字を入れても動作には問題ありません。

話を戻しましょう。

美咲フォントを使った場合です。美咲フォントは8x8の領域を使うので、char型の8つ要素を持つ配列であらわせるのでした。このときの変数名cg0として(宣言時はcg0[8])、このデータを普通に変数cg0にデータを入れた場合、

f:id:niszet:20210421185353p:plain

のようになります。

一方、液晶ディスプレイの方を考えると、文字表示領域には横5ドットしかないため、美咲フォントの1文字は液晶の1つの文字表示領域には収まりません。

表示のさせ方として、今回は文字表示領域間に1マス文字が見えなくなる柱があると思うこととして、となりの文字領域にまたがる場合にその柱の分を加味することとします。ここで、見えないドットを灰色ドットで示すとすると、2列表示モードで一番上の文字表示領域にこの文字を表示する場合は

f:id:niszet:20210421185523p:plain

のようになります。これを、1列モードで表示する場合は、縦に引き延ばしたものを考えれば良いわけですから、次のようになるわけですね。

f:id:niszet:20210421191351p:plain

さて、動画では単純に1列モードで表示するのではなく、字形としてはもう一つ工夫を入れています。それが、横方向への引き延ばしです。

あんまり詳しくないのでふわっとした話ですが、横方向に文字がスクロールするため、液晶の応答(ON->OFFもOFF->ONも)と目が感じる残像(感じるのは脳?)の影響で、この文字が1文字幅だと速度を上げていくと段々見づらくなっていきます。

あと単純に字形も縦長で美しくないですね。元の字形を保ちたいという気持ちがわいてきます。

そこで、元々の字形(再掲)

f:id:niszet:20210421191740p:plain

を横方向に引き延ばした字形として以下のようなデータを作成します。

f:id:niszet:20210421191750p:plain

これは縦方向の引き延ばしと同じように、横方向にも2マス使うようにデータを入れていけば良いわけです。

一点、注意しないといけないのは、一番上に番号を振ったとおり、幅8だったものが幅16になるので、もはやchar型ではデータを持つことが出来ないという点です。char型の変数2つで表現しても良いですが、ここは素直にint型などのより多くのデータ量を持てる型を使いましょう(機種(正確にはコンパイラ依存のはず)によってバイト数が違うとかある気がするのですが、今は16bit=2byte持つことが出来ればよいので、ここは最低限保証されているはず、です)

これを液晶画面に表示するときは、こちらで横に伸ばしたこの字形がさらに縦に引き延ばされ、結果として次のような字形になることが期待できます。

f:id:niszet:20210421192146p:plain

実際には横方向には柱があるという工夫が出来ますが、縦方向の上下に切れる部分はLCDコントローラが勝手にやるので上下にぶった切られてちょっとだけ縦長のバランスになります。ここは妥協するポイントですね。表示しないドットを灰色で示すと、最終的には次のようになります。

f:id:niszet:20210421192851p:plain

ということで、モードの設定と前処理によって表示する字形を制御し、結果として視認性が向上、スクロール速度を上げてもみやすくできる、というお話しでした。

実際にはこれにコントラストやリフレッシュレートなどちょっと細工があるのですが、文字を大きく表示した点が見た目で一番インパクトが出るので、まずはここを押さえると良いでしょう(そう?)

ということで、動画第二弾のための要素技術の話でした。

キャラクタLCDで文字列をスクロールするやつの解説(5回目)

ようやく文字列がスクロールします

これまでのあらすじ

過去4回、約1万1千字を費やして、CGRAMに文字の字形データを入れればどのように表示されるかというレベルまで見てきました。 一旦の区切りとして、今回は文字をスクロールさせるための話です。

前回の記事はこちら。

niszet.hatenablog.com

本題。

さて、あとはスクロールするだけです。前回までにCGRAMに対して変数cg0からcg7までのデータを書き込むことでCGRAMの内容を更新することを説明しました。

察しがついている方もいると思うのですがやるべきことは次の通りです。

  1. 一定時間ごとにcg0からcg7までの変数の中身を横に動くように書き換える
  2. 書き換えたcg0からcg7までの変数を使ってCGRAMの内容を更新する
  3. 結果、書き換えた内容が画面に反映される

これだけです。3つ目はLCDが勝手にやってくれるし、2つ目は前回書いたようにCGRAMへ書き込む処理をもう一度行うだけです。ということで、1つめの「変数を書き換えたら文字が動くのはそうなんだろうけど実際どうやれば文字が動くように変更できるの?」が分かれば出来そうですね!

ということで、やっていきましょう。

余談?

あ、そうだ…。今回、美咲フォントを読み出す話の詳細は書いてませんが、処理はArduino-misakiUTF16ライブラリに依存しているので詳細はReadmeを参照してください…。というかそれも含めてサンプルコード書けばいいんですよね…わかる…。

変数の中身を変更して文字がスクロールするように見せる

変数沢山ありますが、やることは同じなのでcg0を中心に見ていきます。字形はbit列によってあらわされていたので、このbit列を横に動かす方法があれば良いわけですね。

C/C++(他の言語にもあるか?)には丁度良いことにシフト演算子(<<, >>それぞれ左に1つ、右に1つ、bitの並びを動かす。右に動かす場合には算術と…とかはいいか。詳しくは仕様を見てね)があるのでこれでbit列を移動させれば良さそうです。

今、cg0に8'b0000_0100というビットの並びが入っていたとすると、cg0 << 18'b0000_1000になります。簡単ですね!

そういえば、8'b0000_0100という書き方はC/C++ではできません(Verilog風の書き方)が、説明の便宜上使っていますのでご注意。

もうちょっと例を考えます。

シフトして、左側に行き過ぎたらどうなるのか。移動前が8'b0001_0000だった場合には移動後に8'b0010_0000となります。

前回書いたようにCGRAMの上位3bitは画面に表示されないので、CGRAMにコピーする元になる変数cg0も気にせずにシフトすれば良さそうです。

一番左に1があっても1bit左にシフトするとその1は消えてしまいます(もちろん0でも)。これがぐるっと回って右からまた1が現れるといったこともないので、気にせずに左に1つシフトすればよさそうです。反対側、一番右は1bit左にシフトすると常に0になります。

この一番下のbitに右隣の文字からデータを持ってきたいですね。

お隣から拝借

となりの字形データもイメージしたいので図を。隣に動かす場合、右のb4から持ってきたい気もしますが、そうすると字がつながってしまいます。

f:id:niszet:20210420162224p:plain

ここは、間に縦に空白があると思って、b5から持ってくると文字がつながらなくて丁度良い感じになります。

実際、画面の表示はこんな感じで文字の表示領域の間に1ドット分の空きがあります。その分を考慮して(そこに柱があるとおもって、そこに隠れていると考える)作るとより自然な動きになります(最初の動画もこの方法でやっています)

f:id:niszet:20210420162523p:plain

さて、cg1のb5からcg0のb0に値を入れたいわけですが…ひとまずb5の値を一番右に持っていくことにします。これはさっきの逆で右に4つシフトすればよいですね。(cg1 >> 4)こんな感じで。b7, b6には何が入っているかわからないですが、不要なのでここは捨てておきたいですね。こういう時はbit同士の演算で0にするとよいですね。

bit同士の演算には&(and)や|(or)が使えます。0と&を取ると相手が何であっても結果は0になり、1と&をとると相手が0なら0、1なら1、相手のbitがそのまま残ります。 なので、cg1のb5を右端に持ってきたあとに8'b0000_0001と&をとればよさそうですね。8'b0000_0001を16進数の0x01に書き換えれば、

(cg1 >> 4) & 0x01

これでよし。あとはこれをcg0の1桁目に入れてあげるだけ。

それにはこの2つをorで計算すればよいです。orの場合は1とorを取ると相手が何であっても結果は1に、0の場合は相手が1なら1、0なら0で相手のbitがそのまま残ります。 今、cg0の1桁目は0、cg1の1桁目以外は0になっているので、それぞれの欲しかったbitだけが残ってくれるということですね。

ということで、実装例としてはこんな感じになります。cg0やcg1は配列で、長さが8だったのでその分をfor文で処理します。

  for (int i = 0 ; i < 8; i++){
    cg0[i] = (cg0[i] << 1)| (((cg1[i] >> 4) & 0x01);
  }

サンプル表示されていた記号の場合を例に今回のことを図示するとこんな感じになります。イメージ掴めるでしょうか?

f:id:niszet:20210420161038p:plain

さて、これで画面の一番右以外は解決です。一番右はフォントデータから字形を読みだして、それを持ってくる必要があります。…なのですが、これはArduino-misakiUTF16ライブラリの解説になってしまうのでここではざっくりと。やることは上に書いたこととそう変わらないのですが。

フォントデータを持ってくるのはgetFontData()です。これにstatic unsigned char font[8];のように宣言した変数fontを与えるとこの中に字形データが入ります。これの一番左をcg7のb0に入るようにコードを書けば良いわけです。

と、いうことでひとまず一連の説明が終わりです。疲れた…(一度に書くものではないな

いずれ、これらのコード全文を公開すると思いますが(整理中)、中身を理解して、実際に手元で書いてみると色々工夫が出来て楽しいのではと思います。

DDRAMは更新しなくても良い

さて、CGRAMだけを更新するだけでいいの?DDRAMは更新しなくていいの?ということを気にする人がいるかもしれません。 今回の使い方ではDDRAMの更新は不要です。液晶画面の文字座標に対して表示する文字コード自体は変わっていないので、あらためてこの座標にはこの文字コードだよと指定する必要はないのです。文字座標に紐づいた文字コードの字形の入っているCGRAMが書き変わることで、その文字座標の文字も一緒に書き変わる、という仕組みです。

実のところこの更新タイミングをちゃんと制御したいという気持ちがあったのでデータシートも見てみたんですが、関連するパラメータはなさそうです。I2Cだとそこまで制御できないだろうというのもありますが。I2Cの話も追ってかきたいところですね。

液晶ディスプレイの話になりますが、画面の更新、リフレッシュをどのくらいの頻度でやるのか(リフレッシュレート)を制御することが可能で、おそらくそのタイミングで書き換えが出来ていると思うのですが、そのあたりの仕様は書かれていなかったと思います。あったらごめんなさい(教えてね)

と、書いている間に動画をもう一つ上げたので…それも解説しましょうか…。

キャラクタLCDで文字列をスクロールするやつの解説(4回目)

CGRAMの中身の話だよ。

データシートの図をコピペすればよいのではと思うこともあるけども、横着してDS読みに行かない人が出たらどうしようと考えてしまって出来ていないniszetですこんにちは。

さて、このお話も4回目、折り返しです(まだ折り返しか…)

前回の記事

niszet.hatenablog.com

CGRAMはどのように字形を保存しているか

PLCDは文字領域が16x2あるキャラクタ液晶ディスプレイで、各文字は横5dot縦8dotで構成され、CGRAMに外字を登録するということで、今回はCGRAMの中身についての話です。

データシートの17ページ目に書いてあることが全てではあるのですが、ここでは改めてサンプルコードも交えて説明します。

液晶の各ドットのオン/オフによって字形を表現することが出来ます。このオン/オフの状態を数字の1と0にそれぞれ割り当てることでプログラム内で扱うことが出来ます。1と0の状態を表現するデータのことをbit、8bitをまとめたものを1byteと呼んだりしますね。

CGRAMでは行ごとにアドレスを付けていて、上から0,1,2 ... と 7までの8つが与えられています。この行方向にデータをまとめてあげて、それを縦8つ分まとめてあげればCGRAM用のデータの出来上がりです。行単位で1byte、これが8列あって1つも文字分の表示領域の字形データの表現に8byte必要という計算になります。

実際の液晶画面は横に5ドット分しかないので、行方向の1byteのデータのうち上位3bit分は使用されず下位の5bitだけが使われます。この領域にデータを書き込んでも画面の表示に変更はありません。

データを詰め詰めにして5byteにすることも可能でしょうが、このLCDではそうなっていませんね。もちろんそういう実装もありでしょうし、縦方向にすることも考えられますね。でも扱いも煩雑になるので使う側としてはやめてほしいけども。

話がそれたぞ。

Arduinoで(…に限らず、CやC++で)最小単位のデータ型はchar型で1byte、8bitになります。組み込み用のプログラムだと使用できるメモリ量がとても少ないのでデータ量は少しでも減らしておきたいことから、char型をよく使います。今回も丁度良いですね。

サンプルコードではchar cg0[8] ... の8つの配列です。配列の話は…まぁいいか。データの並びを表現するためのものです(割愛)

1点注意としては、このcgなんたらは画面表示のために使いますが、これがCGRAMそのものではないです。CGRAMにこの値を反映するためにはサンプルコードで言うところのplcd_cgram関数で書き込むことが必要です。

さて、そのCGRAMに字形情報を登録する関数、plcd_cgram()ですが今は関数内部実装には立ち入らないことにして、引数(関数に渡しているパラメータ)の意味だけ押さえておきましょう。

定義をみると、

void plcd_cgram(char adr, char *d, int len)

で、それぞれ

  • adr : 文字コードアドレス(外字を登録するDDRAMの文字アドレス。指定できるのは0-7の8つ)
  • *d : char型のポインタ…ここではcg0みたいなデータ列を受け取るもの、までの理解で行きましょう。ポインタの説明は面倒くさいので。
  • len : 配列の長さ。cg0たちはcg0[8]のように全部で8要素入っているので8を与えます。

です。具体的な呼び出し方は

  plcd_cgram(0, cg0, 8);

こんな感じで、文字アドレス0にchar型の配列cg0のデータが送られ、それは要素数が8ですよ、と伝えていますね。この関数を実行するたびに文字アドレス0にcg0で設定したデータが書き込まれます。

では、cg0のデータについて見ていきましょうか。

  char cg0[8] = {0x04, 0x04, 0x04, 0x1f, 0x00, 0x0e, 0x00, 0x04};

0x00みたいな書き方は0xがこれは16進数の表記だよという接頭辞で、うしろの2文字が16進数で2文字で0から255までを表します。10がA、11がB、12がC、13がD、14がE、15がFで0x00-0xFFまでの表現、最大値は16x15+15=255。

配列にデータを与えて初期化する場合は{}で囲います。この辺りはC/C++の文法の話だしいいか。

ここでそれぞれの16進数が10進数で何を表しているか見てもいいんですけど、実際にはこれは液晶の各ドットのON/OFFを便宜的に1と0であらわしたものを束ねているだけなのであまり意味はないです。よって割愛。

逆?に、これらが液晶のドットとどのように対応しているのかを見ましょう。cg0のそれぞれの16進数をbit(2進数)形式であらわすと、それぞれ

8'b0000_0100 8'b0000_0100 8'b0000_0100 8'b0001_1111 8'b0000_0000 8'b0000_1110 8'b0000_0000 8'b0000_0100

となります。頭の8は8bitだよという意味、bはバイナリ(binary、2進数、bitでもいいのかな?)、_は見やすさのための区切りで意味はないです。

0と1で書くとうっすら字形が見える気がしますね?

では実際にお絵かきしてみます。ここでは万能方眼紙であるエクセルを使って描いていますが、エクセルは本来(以下省略)

一応、下に10進数の値も書いてみました。Cって12だから8と4で…1100だな…みたいに計算するために使ってください(?)

cg0の字形は…

f:id:niszet:20210419220713p:plain

サンプルコード下にある写真の左上の図形と一致しましたね!

ということで、CGRAMにどういうデータを入れればどういう字形が表示されるのかがわかりましたね。もちろん、CGRAMにデータを書き込むだけでは液晶画面に表示されないので、サンプルコードのplcd_cgramで字形データを送った後のplcd_data文字コードを所定の座標に書き込むことが必要です。

  plcd_cmd(0x80 | 0); //Set Cursor (0,0)
  for (int i = 0; i < 8; i++) {
    plcd_data(i);
    plcd_data(' ');
  }

このコードでは最初に書き込むためのカーソル位置を0,0に設定し、順に文字コードを0から7まで(8は含まれないので注意)書き込んでいますね。DDRAMに文字を書きこんだらカーソルが1つ後ろにずれるので、これは文字コード0、空白を書き込んで次のループ、文字コード1、空白を書き込んで次のループ…でひとつずつ右に書き込む座標がずれていきます。結果として、CGRAMに登録した図形が1文字おきに表示され、サンプルコード下の写真のように表示されるのでした。

気になる人はCGRAMの他の字形データも写真のようになってるか確認してみましょう。

ということで、CGRAMに字形を書き込んで液晶に表示するまでの話が一通り終わります。

次回、ようやく文字列がスクロールします。長かった…。 察しの良い人はもう気づいている気もしますが…

次の記事

niszet.hatenablog.com