ポケットコンピュータPC-G850VSからTweetする(できた)

# ポケコンでモテたい話

注: この記事は書きかけです

この記事では、PC-G850VS(以下、ポケコン)でTwitterのタイムラインを取得し、
ポケコンからツイートすることを目標とします。

まず前提として、モテるためには平仮名が表示できなくてはいけません。
えっ？機械語が書けない？大丈夫。あなたにもできます。

GOSUB [*/plageoj/items/a7c2598261d50e6034d5](https://qiita.com/plageoj/items/a7c2598261d50e6034d5)

ポケコンとTwitterのインターフェースには、ESP32を使用します。
接続方法については、こちら。

GOSUB [*/plageoj/items/681f3331746871c5f2f8](https://qiita.com/plageoj/items/681f3331746871c5f2f8)

## 通信プロトコルを考える

ひとまずの目標は取得した Twitter タイムラインをポケコンで表示することです。
PC-G850 は漢字 ROM を内蔵していませんので、ESP側でレンダリングして
グラフィックデータを転送することにします。

ポケコンの1行は高さ8ドットですから、同じ高さの[美咲フォント](http://www.geocities.jp/littlimi/misaki.htm)を選択しました。
日本語とANKの高さを揃えられ、改行してもズレません。[^1]

### 通信量を減らす

しかし何も考えずに転送すると、速度が遅すぎます。

というのも、ポケコンの `GPRINT` 命令は1バイトが4ドットに対応するので、
一秒間に転送できるドット数は、改行等を無視してデータだけ送ったとしても
$$ \frac{9600 [\text{baud}]}{10 [\text{bits}]} \times 4 [\text{dots}] = 3840 [\text{dots/sec}] $$

ポケコンの画面は6912ドットあるので、全画面をグラフィック転送すると FPS 0.5 の計算です。
実際はポケコン側の処理待ち＋液晶の応答待ちが入るので、さらに遅くなります。

激しいアクションゲームではないので表示が早い必要はないですが、
全画面の書き換えに3秒かかるのは、現代人には耐えられません。


#### ANKをテキスト転送

まず思いつくのは、ANK[^2]をレンダリングせずテキストで転送することです。
ポケコンできちんと`LOCATE`すれば、グラフィックとの共存が可能です。

文字の横幅が漢字と違うので変に隙間が開くでしょうが…これは仕方ありません。

#### 方針

テキストモードでは、アスキーコード&H20～&HDFまでを受け付け、受け取ったキャラクタを
そのまま`PRINT`します。これで、すべての英数カナが表示可能になります。

漢字はグラフィック転送し、`GPRINT` で直接表示します。

ついでに、はるか昔作ったポケコン用平仮名表示ライブラリを引っ張り出してきて、
平仮名もテキスト転送できるようにします。
平仮名だけであればポケコン内にフォントデータを格納できるので、なんとかなるでしょう(なりました)。

平仮名と片仮名は同じキャラクタコードをあてがいます（一番かんたんなので）。
後述する独自制御コードでモードを切り替えながら転送します。

余った &HE0～&HFF までの32文字は、独自制御コードに充てます。

### 必要なコマンド

#### 表示コマンド

まずは、ESP32からポケコンへ送信するコマンドです。
これには、独自制御コードの範囲 &HE0～&HFF までを使用します。

この範囲にないコードは表示データとして処理します。

|コード|内容|
|:---|:---|
|&HE1|PHRG 出力をひらがなモードにします|
|&HE2|PANK 出力を ANK モードにします|
|&HE3|PGRP 出力をグラフィックモードにします|
|&HEE|END このツイートはここまでです|
|&HF0|NL 表示上の強制改行。CRLFは入力の終端と解釈されてしまいます|

#### 制御コマンド

これは、ポケコンからESP32へ送信するコマンドです。
このコマンドには、すべてのキャラクタコードが使えます。
一連のコマンド終了後はすべて `\n` (CR LF) を送信します。

|文字|内容|
|:---|:----|
|-|ポケコンのバッファが空であることを通知します<br>ESP がコマンド受付状態かどうか確認します|
|>|次のツイートを取得します|
|<|前のツイートを取得します|
|/`Query`|検索します|
|N`Content`|ツイートします|
|U`UserName`|ユーザータイムラインを取得します|

## ESP32 で Twitter API を叩く

さて、簡単そうな割に難易度が高いのが、ESP から Twitter を直接叩くことです。

実際、SDK が公開されている言語が動く踏み台を別途用意して、それを呼び出して
やるのが ESP の実装としては簡単なのですが、それではポケコン最大の武器である
モビリティを盛大に犠牲にしてしまいます。

このクライアントは Wi-Fi と電源さえあれば単体で動くべきなのです。

### Request

[Twitter API から Arduino – ESP32 を使ってトレンドツイートを取得してみた](https://www.mgo-tec.com/blog-entry-twitter-api-arduino-esp32-trend-get.html)
なるページを公開してくださっている mgo_tec 氏に最大の感謝をしつつ、こちらで
使われているソースをベースに作っていきます。

しかしながら、こちらのソースはライブラリではなく、トレンドツイートの取得専用に
作られているため、ユーザータイムラインをとるためには署名に必要な要素が足りません。
これに関しては自前で作っていく必要があります。

また、検索ワードやツイート内容はポケコンから送信するので、決め打ちではいけません。
この前提で、関数に適切な引数を設定してやる必要があります。

### Refactor

そうこうしているうちにファイルが500行を超えてしまいました。
このままでさらにポケコンへの出力ルーチンを組み込むのは無理があるので、
いい感じにライブラリとしてインクルードできるように形式を整えて分割しました。

<details>
<summary>このタイミングで IDE を Arduino から Visual Studio Code + PlatformIO に切り替えました。</summary>
ファイルが大きくなりプログラムが複雑になったため、Arduino では関数を探すのが大変になっていました。
そこでインテリセンスのきく PlatformIO を選択しました。<br>
結果、複数ファイルの横断や関数定義の検索が素早くできるようになり、開発の効率に
大きく貢献しています。
</details>

### Response

Twitter API の返事は JSON で返ってくるのですが、いかんせん巨大すぎて、Arduino の
JSON ライブラリではメモリに展開できずに死んでしまいました。

そこで、表示上必要な最低限の要素だけピックアップしてあとは捨てる、オレオレパーサを書きます。

具体的には、

* 表示名
* ユーザーID
* ツイート本文
* ツイートID（後でリプライやいいねができるようにする）

を選択しました。

### Render

#### 漢字

さらに mgo_tec 氏の力を借ります。
[ESP32-WROOM-32 の SPIFFS を使って、日本語漢字 美咲フォントを読み込む](https://www.mgo-tec.com/blog-entry-spiffs-esp-wroom-32-misaki-font.html) にあるライブラリをベースに、上記で得られる UTF8 の文字列をグラフィックデータに変換すればよいです。
なお、半角文字用のフォントは使いませんから、半角フォントは格納不要です。
読み込まないだけではエラーが出るので、ライブラリの関係部分をまるまる削除してしまわなくてはいけません。

これで得られるフォントデータは90度回転しているので、反対向きに回し直して
ポケコンのフォーマットに合わせます。

#### ひらがな・カタカナ

基本的に我々が使うのは全角カタカナですが、上記のルーチンに食わせる前に半角カナに変換します。このテーブルは自作です……
転送前にひらがなかカタカナか判定して、それに合ったモードに切り替えればよいです。

ひらがなモードではひらがなしか転送しないという制約を課すことで、
この記事最初にあるひらがな出力ライブラリの文字範囲判定関係のロジックを飛ばせますから、
表示は比較的高速になるでしょう。
また、漢字←→ひらがなの切り替え時には、余計な空白が出力されないようにします。

#### 英数字

何も言うことはないです。

他のモードで出力しているとき、安定をとってテキストモードに切り替えてはいけません。
次のテキスト出力位置に合わせるために、余分な空白が出てしまうからです。

## 漢字を入力する

[Google 日本語入力の API](https://www.google.co.jp/ime/cgiapi.html) があります。
自前で辞書を用意しなくても、この API を叩けば変換結果が得られます。ありがたや。

ただし、ここには UTF-8 のひらがなでリクエストを飛ばす必要がありますから、
SJIS 半角カタカナ → UTF-8 全角ひらがなのテーブルは自作します。

[^1]: ジオシティーズなので[魚拓もとっておきます](https://web.archive.org/web/20181101035341/http://www.geocities.jp/littlimi/misaki.htm)。

[^2]: Alphabet, Number, Kana の略です。1バイトで表現可能な、所謂半角文字を指します。