0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IchigoJam 2台で1対1の簡易チャット

Posted at

IchigoJam 同士で通信ができる、簡易チャットプログラムを作ってみた。

※IchigoJamはjig.jpの登録商標です

プログラム

※1.4系以降専用

10 ' チャット
20 UART0:CLS:CLV:W=POS(3):H=POS(4):LOCATE0,H-2:FORI=1TOW:?CHR$(#91);:NEXT
30 LET[0],#B2B1,#3EC3:R=4:D=0:E=0:LOCATE0,H-1,1:?"アナタ:";:S=4:C=4:B=#900+W*H-W
40 K=INKEY():IF!KWAIT1:GOTO40
50 K=K&#FF:IFK<8D=K<<E+D:POKE#800+R,D:R=R+(R<W+1ANDE=6):E=(E+3)%9:D=D*!!E:GOTO40
60 IFK=22R=4:D=0:E=0:GOTO40
70 IFK=25COPY#900,#900+W,W*(H-3):COPYB-W*2,#840,W:COPYB-W*2,#800,R:R=4:D=0:E=0:GOTO40
80 IFK=28C=C-(C>4):GOTO160
90 IFK=29C=C+(C<S):GOTO160
100 IFK=18C=4:GOTO160
110 IFK=23C=S:GOTO160
120 IFK=8ANDC>4COPYB+C-1,B+C,S-C+1:C=C-1:S=S-1:GOTO160
130 IFK=127ANDC<SCOPYB+C,B+C+1,S-C:S=S-1:GOTO40
140 IFK=10ANDS>4UART9:?CHR$(22);:FORI=4TOS-1:V=PEEK(B+I):?CHR$(V&7,V/8&7,V>>6);:NEXT:?CHR$(25);:UART0:COPY#900,#900+W,W*(H-3):COPYB-W*2,#840,W:COPYB-W*2,B,S:COPYB+4,#840,W-4:S=4:C=4:GOTO160
150 IFK>31ANDK<>127ANDS+1<WCOPYB+S,B+S-1,C-S:POKEB+C,K:C=C+1:S=S+1
160 LOCATEC,H-1:GOTO40

2台の IchigoJam でこのプログラムをそれぞれ実行し、それぞれの RX をもう一方の TX に導線などで繋いで通信を行う。(GND 同士も接続する)

プログラムを実行していない時に TX と RX を接続すると、一方の IchigoJam が出力したメッセージを他方がコマンドとして実行しようとし、予期せぬ事象が発生する場合がある。
他方の IchigoJam への接続は、プログラムの実行中、もしくは実行直前に行うこと。

実行結果例

プロトコル

IchigoJam では、キーボードで入力した内容も、UART で受信した内容も、同じ INKEY() 関数で読み込むことになる。
そのため、何も工夫をせずに入力した内容をそのまま UART で送信してしまうと、読み込んだのか自分が入力したデータなのか、相手から送られてきたデータなのか、わからなくなってしまう。

そこで、今回は
IchigoJamの特殊キーコード表(特殊キャラクターコード表) by 表かんたん作成プログラム
を参考に、通常は入力しないはずであり、かつ特殊キーコードとして使用されていない 0~7、22、25 を相手へのデータの送信に使うことにした。

具体的には、入力されたメッセージを以下の形式で送信する。

  1. 22 (メッセージの開始を表す)
  2. 文字コードの下から 0~2 ビット目
  3. 文字コードの下から 3~5 ビット目
  4. 文字コードの下から 6~7 ビット目
  5. 2~4 を残りの文字の数だけ繰り返し
  6. 25 (メッセージの終了を表す)

メッセージを、メッセージの開始や終了を表すコードで挟むことで、もし通信がうまくいかずにあるメッセージの一部バイトが欠損しても、他のメッセージには影響を与えにくいようにすることを狙った。

プログラムの解説

初期化

10 ' チャット
20 UART0:CLS:CLV:W=POS(3):H=POS(4):LOCATE0,H-2:FORI=1TOW:?CHR$(#91);:NEXT

余計なデータを UART に送信しないようにする。
画面と変数領域をゼロクリアする。
画面の幅 W と高さ H を取得する。
発言ログを表示する部分と、編集中の発言を表示する部分を区切る線を描画する。

30 LET[0],#B2B1,#3EC3:R=4:D=0:E=0:LOCATE0,H-1,1:?"アナタ:";:S=4:C=4:B=#900+W*H-W

自分の発言の処理に用いる領域 (画面の最下行) のアドレスを変数 B に格納する。
相手の発言を格納する領域の前に、文字列「アイテ>」を置く。
自分の発言を格納する領域の前に、文字列「アナタ:」を置く。
カーソルの表示を有効化する。
以下の変数を初期化する。

  • R:相手から受信した文字を次に格納する位置
  • D:相手から受信中の文字
  • E:相手からの文字の受信状態
  • S:自分の発言の最後の文字の次の位置
  • C:自分の発言を編集するカーソルの位置

入力の読み取り

40 K=INKEY():IF!KWAIT1:GOTO40

INKEY() で入力を読み取る。
入力があるまで待機する。

相手の発言の受信

50 K=K&#FF:IFK<8D=K<<E+D:POKE#800+R,D:R=R+(R<W+1ANDE=6):E=(E+3)%9:D=D*!!E:GOTO40

0 の受信は #100 として表されるので、#FF とのビットANDをとって 0 に戻す。
受信したのが 0~7 の場合、以下を行う。

  1. 受信中の文字に、受信したビットを加える
  2. 受信中の文字を、受信したデータを保存する領域に書き込む
  3. 1文字完成して、かつ受信したデータが長すぎでない場合は、受信した文字を書き込む位置を進める
  4. 受信の状態 (次に受信するデータのビット位置) を進める
  5. 1文字完成した場合は、受信中の文字をクリアする
60 IFK=22R=4:D=0:E=0:GOTO40

22 (メッセージの開始を表す) を受信したら、発言の受信状態をリセットする。

70 IFK=25COPY#900,#900+W,W*(H-3):COPYB-W*2,#840,W:COPYB-W*2,#800,R:R=4:D=0:E=0:GOTO40

25 (メッセージの終了を表す) を受信したら、受信したメッセージを画面に反映する。
具体的には、以下を行う。

  1. 発言ログを1行上にスクロールする
  2. 発言ログの最下行をゼロクリアする
  3. 発言ログの最下行に、受信した発言と、その前に用意した アイテ> をコピーする
  4. 発言の受信状態をリセットする

自分の発言の編集と送信

80 IFK=28C=C-(C>4):GOTO160
90 IFK=29C=C+(C<S):GOTO160
100 IFK=18C=4:GOTO160
110 IFK=23C=S:GOTO160

左キー・右キー・Homeキー・Endキーによるカーソルの移動を行い、それをカーソルの表示に反映する。

120 IFK=8ANDC>4COPYB+C-1,B+C,S-C+1:C=C-1:S=S-1:GOTO160

BackSpaceキーの処理を行う。
具体的には、カーソルが左端以外にあるときのみ、以下を行う。

  1. カーソルの位置から最後までの発言内容を、1要素前にコピーする
  2. カーソルを1文字前に移動し、文字列の長さを1減らす
  3. カーソルの表示を更新する
130 IFK=127ANDC<SCOPYB+C,B+C+1,S-C:S=S-1:GOTO40

Deleteキーの処理を行う。
具体的には、カーソルが最後の文字の次以外にあるときのみ、以下を行う。

  1. カーソルの位置の次から最後までの発言内容を、1要素前にコピーする
  2. 文字列の長さを1減らす

この操作ではカーソルの位置は変わらないので、カーソルの表示の更新は行わず、すぐに次の入力の受け付けに移る。

140 IFK=10ANDS>4UART9:
    ?CHR$(22);:FORI=4TOS-1:V=PEEK(B+I):?CHR$(V&7,V/8&7,V>>6);:NEXT:?CHR$(25);:
    UART0:COPY#900,#900+W,W*(H-3):COPYB-W*2,#840,W:COPYB-W*2,B,S:COPYB+4,#840,W-4:
    S=4:C=4:GOTO160

発言が1文字以上ある状態でEnterキーが押されたら、発言を送信し、自らの発言ログに加える。
具体的には、以下を行う。

  1. UART のみに出力するモードにする
  2. 発言の開始を表す 22 を送信する
  3. 発言の内容を送信する
  4. 発言の終端を表す 25 を送信する
  5. 画面のみに出力するモードにする
  6. 発言ログを上に1行スクロールする
  7. 発言ログの最下行をゼロクリアする
  8. 発言ログに アナタ: と発言内容をコピーする
  9. 発言内容をゼロクリアする
  10. 発言内容の長さとカーソルの位置をリセットする
  11. カーソルの表示を更新する
150 IFK>31ANDK<>127ANDS+1<WCOPYB+S,B+S-1,C-S:POKEB+C,K:C=C+1:S=S+1

文字が入力された際、発言内容の長さが上限未満なら、それをカーソルの位置に挿入する。
具体的には、以下を行う。

  1. カーソルの位置から最後までの発言内容を、1要素後ろにコピーする
  2. カーソルの位置に入力された文字を置く
  3. カーソルを1文字後ろに移動し、文字列の長さを1増やす
  4. カーソルの表示を更新する
160 LOCATEC,H-1:GOTO40

カーソルの位置を画面に反映し、次の入力の受け付けに移る。

おわりに

最低限の機能を持ったチャットプログラムを作り、IchigoJam 2台の間で通信を行うことができた。

「アナタ」「アイテ」のかわりに自分の名前を設定できるようにし、3台以上で通信を行うことができるようにすると、より本格的になるだろう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?