2009年11月20日(金)
シリアル通信(4)
MSXの受信側プログラムを書いているところだが、予想どおり難航中。
ステート数を数えたりしているが、なかなかうまくタイミングが取れない。
イライラしているところに、イライラするCMに出くわしたので、八つ当たり気味に紹介しておく。
サッポロビール「オフの贅沢」。
見慣れない店のまえで男が足を止める。入ってみると女将が飲み物メニューを差し出す。
「ふつう」 と 「贅沢」。
男が「ふつう」と答えると、女将は「あら、意外」。「じゃ、贅沢」と答えると、「単純」。
ムカッ。「どないせえっちゅうんじゃっ! ワシは帰る!」と、自分なら席を蹴るところである。
サッポロビールは何を考えてこんなCMを作ったのか?
とき前後して、サッポロビールの社長が傷害容疑告訴で書類送付されるという「事件」が起きた。
酔っ払った社長が「感謝の意を表すため」、お店の女性のほおを両手ではさむように叩いたとされている。
同社は「手で挟んだ、という認識」としているが、たとえ本当に感謝の意を表すためとはいえ、人前で女性の顔に手を触れるなんてことを普通、するかい?
というわけで、サッポロビールは「普通じゃない」というオチがついてしまった次第である。
なもんで、受信側プログラムがうまくいかない今日この頃である。
2009年11月19日(木)
シリアル通信(3)

■実体配線図
MSXの汎用入出力ポートの8ピンは、起動時LOWである。一方、RS232Cぽい通信では、無信号時はHIGHで、スタートビットのLOWにより通信が開始される。
8ピンの状態を無信号時HIGHに反転するため、74LS14を加えている。74LS04でもいいと思うが、波形がしゃきっとするような気がする。伝送が遅延するというウワサは気にしない。
■送信波形
9600bpsにおける1bitの信号幅は約104μ秒。一方、MSXの1ステートは0.294μ秒。
従って、1bitの信号幅で処理できるステート数は、
104μ秒 ÷ 0.2794μ秒 ≒ 373
により、約373ステート分となる。
例えば「NOP」は本来4ステートのところ、MSXではマシンサイクル1回に付き1ステートのウエイトが入るので、計5ステートとなる。
373 ÷ 5 ≒ 75
により、9600bpsにおける1bitの信号幅は、NOPを約75回実行した長さに相当する。
以上をもとに、アセンブラソースのステート数を数えようと思ったが、面倒になってきた。
というわけで、スタートビットの立下りからストップビットの立上りまでの計算上の時間(938μ秒)と同じような波形になるよう、ウエイトループを調整した。
どうせ信号幅の許容誤差3〜5%のおおらかな通信仕様であり、結果オーライである。
■奇妙な現象
ところで、奇妙な現象に気づいた。
普段からSONYのHBI-J1を用いて漢字モードを常用しているのだが、試みにANKモードで試してみると、なぜか文字化けが増加する。
機械語プログラムでは、割り込み禁止してPSGを直接操作しているので影響ないはずである。
BASICプログラムでも大したことしていないので、影響が出るとは思えない。
今後の原因究明が待たれる。待っていて解決するのか知らんが。
■今後の展開
ひとつはPCとの連携。もうひとつはMSXどうしの連携。いずれも、MSX側の受信環境を整える必要がある。
受信は送信に比べ、難易度が格段に高くなる。
また、turboRへの対応も必要かなと思うが、一時的にZ80モードにすればええのんとちゃう? と気乗り薄である。
2009年11月14日(土)
シリアル通信(2)
■BASICプログラム
前回に書いたとおり、送信したい文字列はUSR関数の引数として渡す。
MSXの場合、文字列は255文字までという制限に留意すべきである。
今回は、「引数として文字列をUSR関数に渡す」という仕様にしたため、このような制限がある。これにこだわらなければ、アセンブラソースを書き換えて、16ビット長のデータも扱えるはずである。
今回のテストしたプログラムは次のとおり。
100 '================
110 ' SERI.BAS
120 ' SERIAL OUT TEST
130 '================
140 'SAVE "SERI.BAS"
150 CLEAR 200,&HBFFF:BLOAD"SERIBAS.OBJ"
160 DEFUSR=&HC000:LF$=CHR$(10):CR$=CHR$(13)
170 FOR I=32 TO 126
180 D$=CHR$(I):D$=USR(D$)
190 NEXT
200 D$=USR(CR$):D$=USR(LF$)
">
MSXは、SONYのHB-F900を使用。写真右下の赤い小さなブレッドボードがインターフェース。
MSX本体に載っている左側画面はMSXのモニタ。右側がSA-1Fパソコン。文字コード32〜126の文字を表示している。ターミナルソフトは「Tera Term PRO」。MSX風に青地に白文字にしてみた。

パソコン側で受信しているさまをGIFアニメにしてみた。少〜し実際よりも早目に表示されている。
マシン語部分の転送速度は9600bpsであるが、BASICの部分で時間がかかっている。1文字ずつ送信しているためであって、送信データをまとめてバッファに格納し一気に送信すれば9600bpsの実力が発揮できるはずである。
受信側のパソコンの処理能力に余裕があるのでフロー制御なしでも大丈夫であるが、パソコンからMSXに送信する場合は、データの取りこぼしが予想される。
MSXの受信プログラムも書こうと思っているが、たいてい受信側のほうが面倒なんだなあ。
2009年11月13日(金)
シリアル通信(1)
以前から考えていたものの、なかなか着手せずにいた、MSXによるシリアル通信に着手。
■1 仕様
(1) ベースはBASIC
やっつけ仕事に柔軟に対応できるBASICをベースとする。当然、USR関数による引数渡し。
CLEAR 200,&HBFFF:DEFUSR=&HC000
A$="ABC":DUMMY$=USR(A$)
てな調子である。
(2) RS232Cっぽい仕様
転送速度は9600bps固定。スタートビット1、データビット8、パリティなし、ストップビット1。フロー制御なし。
なぜ9600bps固定かというと、転送タイミングを機械語命令数に依存しているため。
今どきの機器は9600bpsでも十分こなせるはず。
PC/AT互換機のシリアルポートに似ていることもあり、例によって汎用入出力ポートを使用。
(3) RS232Cぽくない仕様
12Vレベル変換は行わず、TTLレベルのまんまとする。
今どきの機器は、内部では5Vとか3.3Vで処理しているくせに、シリアルポート部分だけは12Vに上げたり下げたりしている。んな面倒なことはしない。
■2 ソフトウエア
ざっと仕様を書いたところで、アセンブラソースを書き始める。いつものとおり、ASM.COM用である。
動作の概略は次のとおり。
(1) USR関数の変数型チェック。文字列でなければリターン。
(2) 文字列の長さをチェック。ゼロならリターン。
(3) 文字列の長さがゼロになるまで、信号を送出する。
※ここまでは、「MSX2テクニカル・ハンドブック」と、ほぼ同じ。PSGレジスタ#15のデータ保存を紛れ込ませている程度の改変。
(4) まず8ピンを下げて、ストップビットの送出。
(5) LSBから順番に8ピンを上げ下げ。
(6) 最後に8ピンを上げて、ストップビットを送出。
※「上げ下げ」とソースコードが逆ではないかと思っている人がいるかもしれないが、その点は後述。
(7)サブルールーチンは、PSGレジスタ#15のデータセーブ。8ピンの上げ下げ。ウエイトループ。
※NOP命令を繰り返しているが、DJNZで結構時間を喰ってしまい、大味なウエイトループになっている。もうちょびっとウエイトがほしいので、ループ外にもNOPを足している。
■3 ハードウエア
(1) 主な部品
・Dサブ9ピンコネクタ(メス):金属部分を外して、ポートに接続しやすくした。
・74LS14:MSXの起動時点では8ピンはLOWであることに後から気が付いて、論理を反転するために入れたもの。このため、上述のソフトウエアの論理をもう一度反転するさせた。考えてみれば、サブルーチンの中で反転しておけば読みやすかったかもしれない。CPLなんて命令も入っていて、まるで「反対の反対なのだ!」状態である。
・USBシリアル変換アダプタ:ここではFT232RLを使ったsparkfunの製品を使用。
(2) 結線
・MSXの5VとGNDを74LS14に結線。
・MSXの8ピンを74LS14の1ピンに結線。
・74LS14の2ピンをアダプタのRXに、GNDをGNDに結線。
・パスコンとかプルダウンは適宜。
■まとめ
さて、どうなることやら。続きはコマーシャルのあとで。

赤くてかわいいブレッドボード。これがインターフェース。
74LS14とsparkfunのFTDI Basic Breakout(5V)が載っている。後者は秋月のUSB-シリアル変換モジュールも使えるはず。
2009年11月7日(土)
いろいろ試み中
Aruduinoはお手軽でいいのだが、少々割高である。
最もスタンダードなArduino Duemilanoveで、3200円ぐらいか。
ちょこちょこっと実験(いたずら)してみる分にはいいのだが、完成品に組み込んでしまうのは、そのお値段故に気が引ける。
というわけで、もう少し安上がりそうな製品を試しているところである。

中央の小さいのは、Arduino Pro Mini。
プログラムの書き込みには、別途USB-シリアルアダプタが必要となるが、本体だけなら2,100円。純正Arduinoの中では、最も安いのではなかろうか?
写真では、1.5V→5Vの昇圧DC/DCコンバータ付きの電池ボックスを使って、単三電池1本で駆動している。
左側の細長いのは、トランジスタ技術2008年8月号に付属していた78K基板。
今年(2009年)8月に刊行された「USBマイコンでパソコンI/O!」(CQ出版)にも付属しており、3,800円。
書籍込みではArduino Duemilanoveより高くなるが、マルツでボードだけ買えば1,980円で済む。
開発環境は、書籍付属のCDに収められている。ボードにはトラ技BIOSなるモニタが書き込まれており、作成したHEXファイルをターミナルソフトから転送して書き込むことができる。
拡張RAM領域に転送した場合は、電源を切るとプログラムも消えてしまうが、ROM領域に転送すれば、電源を供給するだけでパソコン不要の使い方もできる。
これら以外にも、秋月のUSBマイコンボードPIC18F2550(1,000円)や PIC18F4550(1,100円)も近いことができるかもしれないが、別途、プログラムの書込み機が必要で、AKI-PICプログラマーVer.4(完成ボード)の場合、5,700円也である。面倒なんだなあ。せっかくUSBコネクタを装備しているのだから、USB経由で書き込みさせてほしいところである。

ということで、78K基板を試してみた。
PM+という統合環境で、サンプルプログラムの「ledmain.c」を改変。ビルド後に出来上がったHEXファイルをTera Termから転送。
「かえるのうた」を演奏するプログラムであるが、オリジナルはタイミングがかなりヘンである。
修正後もまだヘンではあるが、オリジナルよりマシであろう。文末のアイコンをクリックすると再生されるはず。
元の音色は安っぽいので、ちょいとエフェクトをかけておいた。
音が小さいかもしれないが、そのときは音量を上げるように。大きすぎるときは下げるように。
以下はソースの一部。ブログシステムの都合上インデントが効かないので、全角スペースで代用した。
音程と音長をどちらもwait()で処理しているので、正確なタイミングがとり辛いのじゃ。
#pragma sfr
#include "types.h"
#include "trgbios.h" // トラ技BIOSのサービスルーチンを呼び出すのに必要
void wait(U16 len) { // len回のNOPを実行してWAITを行う
while(len--){
#asm
NOP
#endasm
}
}
void buzz(U16 tone,U16 len) { // P01端子を操作してブザーを鳴らす
U16 x;
for(x = 0; x < len; x ++){
P0.1 ^= 1;
wait(tone);
}
}
const char KAERU[] = "かえるの歌を演奏します。P01端子に圧電サウンダを接続してください。\n";
void main() { // メイン
U16 i;
PM0 = 0xfc; // ブザーの端子
trg_puts(KAERU);
P6.1 = 1;
buzz(1000,100);
P6.1 ^= 1;
buzz( 900,100);
P6.1 ^= 1;
buzz( 800,100);
〜音楽データ中略〜
while(1){
trg_puts("zキーを押してください\n");
if(trg_getc() == 'z') break;
}
trg_puts("\n");
P6.1 = 0;
}