ホームページH8をMacで>その7c・TOPPERSに移行する(MP3シリアル転送編)

その7c・TOPPERSに移行する(MP3シリアル転送編)

目次
 目的と経緯

 以下は、マイコンボードのOSをMESからTOPPERS/JSPに移行した際の覚書です。

 という訳で(どういう訳だ)、TOPPERS/JSP復帰第1弾は、「MP3デコーダへのデータ転送をシリアル通信で行ってみる」です。
 以前MESでテストした際、MP3の転送時間が再生時間と同じという結果に終わったため、これの高速化を目指し、TOPPERS/JSP上で継続調査していきます。
 手始めとして、転送方法をシリアル通信に変更して、通称「手クロック」方式と比較してみることにしました。


 方針

 H8/3069Fはシリアルポートを3つ持っていますが、SCI0とSCI1は、外部との通信用にTTL変換されたものが、ボード上に実装されています。(SCI1はRS232C端子、SCI0は3ピン端子)
 なので、信号線直結で使えるのはSCI2、即ちポートBということになります。
勿論、ボードに手を加えて変換チップの手前で取り出すことは可能だが、今回はそこまでしない。
 ですが、ポートBは既にSDカードIF用にアサインされています。
 とはいっても、現状、ポートBは通常のポートとして使っているので、要はシリアル用に割り当てられた端子を避けて使用すればいい訳です。
シリアル端子は複数の機器で共用できるようだが、うまく行かなかった時の原因究明を容易にするため、ここでは共用しない。
 ということで、まずはSDカードIFを移動して動作確認し、その後、MP3デコーダ用の信号線を移動してきて、実験することにします。


 前準備

 <MES -> TOPPERS/JSP移植>

 シリアルポートの実験に入る前に、まずは現状で、TOPPERS/JSP上でMP3ファイルの再生が出来るようにします。

 作業の方針は以下の通りです。
・MP3ファイルはSDカードから読み出すため、ベースには「その7b」で使用した、FatFsを組み込んだセットを用いる。
・MP3転送部分は、以前MES用に作成した「MP3モジュールテストプログラム(サンプルファイル)」から切り出したものを、TOPPERS/JSP用に改変する。

 改変後のプログラムをビルドし、実機に転送して実行させたところ、正常に再生されることを確認しました。

 なお、上記試行に用いたプログラムのソースはこちらから。

 <ピンの移動>

 シリアルポート用ピンを空けるため、SDカードIF用のピンを、以下のとおり移動します。

・DI端子を、従来のPB6(39番ピン)からPB2(35番ピン)に移動。
・DO端子を、従来のPB7(40番ピン)からPB1(34番ピン)に移動。

 あとは、ピンの移動にあわせてソース(toppers_fatfs/source/config/h8_akih8_3069f/mmc.c)を修正します。
#define MMDI        PBDR.BIT.B2		/* MMC DI */ // MESベースから変更
#define MMDO        PBDR.BIT.B1		/* MMC DO */ // MESベースから変更
…
DSTATUS disk_initialize (
 …
)
{
	PBDDR = 0x0D;		/* I/O port の種別を指定(入れる場所は検討の余地あり) */
 …
 改変後のプログラムをビルドし、実機に転送して実行させたところ、正常に再生されることを確認しました。
注1:ポートBの使用に拘るのは、単にワイヤーの長さが足りないためであり、余裕があれば別のポートであっても構わない。
注2:当初、DO端子用としてPB4(37番ピン)を使おうとしたが、読み込み時にハングアップしてしまった。理由は不明。(TOPPERS/JSP側で何かしている?)

 経過

 ようやくシリアルポートの出番です(笑)。

 まずはハードウェアですが、MP3デコーダのCLK, DI, DOを、それぞれ38, 39, 40番ピンに繋ぎ変えます。(変更はこれだけです。)

 次にソフトウェアですが、TOPPERS/JSP(1.4.3)のマニュアルを見ると、
・H8/3069Fのシリアルポートは3本まで認識できる
・ただし、デフォルトでは2本(SCI0, SCI1)まで認識している
・通信方式は、デフォルトでは調歩同期方式となっている

 今回使用したいのは、キャラクタ端末用としてではなく、データ転送用としてなので、調歩同期ではなく、クロック同期を選択したいところです。
 ですが、調歩同期とクロック同期では手続きが異なるので、単に当該ビットの切り替えだけでうまく行くのかが良く分かりません。

 SCI2がデフォルトではシリアル通信用としてアサインされていないこともあるので、ここは、自分で追加することにしました。
 とは言っても、一から書き上げる力はないので、ググってみたところ、以下の事例がヒットしました。

 参考サイト(1):mikan++>TOPPERS>FatFsの移植

 そこで、これを使わせて頂くこととしました。(注:MMC用ですが、MP3転送にも流用できます。)
  1. 上記「前準備」で使用したsample1.cに、参考サイト(1)の以下を追加
    ・インクルードとレジスタ定義(全行。要らない行もあるかも)
    ・Port controls(「SOCKPORT」行。要らないかも)
    ・SPI入出力(「xmit_spi(dat)」と「rcvr_spi_m(dst)」)
    ・Power control(power_on (void)の中身。ただし「Wait for 30ms」行と「準備OK」行は除く。vs_init()の前に追加)

  2. sample1.cの、以下を書き換え
    int sci_write(unsigned int addr, unsigned int dat)
    {
    	while((P8DR.BYTE & 0x01) != 0x01);  // Wait for DREQ High
    	PADR.BYTE = 0x38;  // xRESET High + xDCS High + xCS High
    	PADR.BYTE = 0x30;  // xCS Low
    	xmit_spi(0x02);
    	xmit_spi(addr);
    	xmit_spi(dat>>8);
    	xmit_spi(dat);
    	PADR.BYTE = 0x38;  // xCS High
    	return 0;
    }
    
    int vsread()
    {
    	int i, dat;
    	char tmp1, tmp2;
    	dat = 0;
    	rcvr_spi_m(&tmp1);
    	rcvr_spi_m(&tmp2);
    	dat = tmp1;
    	dat = tmp2 + (dat<<8);
    	return dat;
    }
    
    int sci_read(unsigned int addr)
    {
    	int dat;
    	while((P8DR.BYTE & 0x01) != 0x01);  // Wait for DREQ High
    	PADR.BYTE = 0x38;  // xRESET High + xDCS High + xCS High
    	PADR.BYTE = 0x30;  // xCS Low
    	xmit_spi(0x03);
    	xmit_spi(addr);
    	dat = vsread();
    	PADR.BYTE = 0x38;  // xCS High
    	return dat;
    }
    
    //  メインタスク
    void main_task(VP_INT exinf)
    {
     …
    			for(i = 0; i < 32; i++){
    				xmit_spi(buff[j+i]);  // vswrite(buff[j+i]); を置き換える
    			}
     …
    }
    
 改変後のプログラムをビルドし、実機に転送して実行させたところ、正常に再生されることを確認しました。
当初はノイズ混じりのぼやけた音だったが、(関数名が分からなかったために無効化してあった)割り込み禁止処理を復活させたところ、正常になった。

 考察

 肝心のデータ転送時間ですが、「手クロック」と比較して、全くといっていい程変わりません。
 ということで、手クロックが原因で速度が出ない、という訳でもなさそうです。

 SDカードから転送できるようになったこともあって、「じゃぁ、SDカードMP3プレーヤーを作成されている他の方はどうしているの?」と疑問に思って、少し調べてみたところ、「SDカードからシリアル通信でデータを受け取り、その都度MP3デコーダに渡す」という方式を取っているものがありました。

 もし、転送を開始してから次にDREQがHになるまで演奏時間分かかるとしても、Hになるまで延々待ち続けている時間をデータ取得に割り当てておつりがくるようであれば、連続的に再生できることになります。
この場合、転送自体は一瞬で終わることが前提。
現状、精密に各ステップの時間を計測する手段がない(たぶん、何らかの計測機器が必要)ので、あくまで推測。
なお、試しにmmc.c内のrcvr_datablock()で、rcvr_spi()直後にMP3デコーダに送ってみたが、ノイズ混じり&スロー再生になってしまった。さすがに無茶か…
 どうも、高速化(DREQがHになるまでの時間短縮)という方向では解が見えてこない感じです。
こうなってくると、何か根本的なところで考え違い/勘違いをしているような、そんな気がしてくる…
 <おまけ>
 ついでと言ってはなんですが、ピンを繋ぎ変えて、SDカードのアクセスにも適用してみました。
 元々MMC用なので、mmc.cを差し替えてみましたが、ビルドは通るものの、実行させるとファイル読み込みの時点でハングアップしてしまいます。
 原因は良く分かりませんが、元のmmc.cがR0.04、差し替えがR0.07aのものなので、この辺が影響しているのかもしれません。
(ff.cとかも入れ替えると、コンパイルすら通らなくなるので、深追いはしていません。)

 追記:その後、FatFsの作者様のサイトで、f_forward()という、ファイルから読み出したデータを送信ストリームに直接転送する関数があることを知りました。
 ただし、これが実装されたのはR0.06からなので、まずはR0.04からR0.06以降に差し替える作業が必要になります。
 いずれ試してみたいと思います。(2009.12.15)


 今後の課題

 前述の方法は、SDカードには使えても、インターネットラジオには使えそうもありません。
 おそらくは、OSレベルでの並行処理が必要になると思われます。

 TOPPERS/JSPにおける、タスクとメールボックスなるものの調査、ということになるのでしょうか。

 「その9・インターネットラジオを聴きたい(ほぼ解決編)」へ続く


 お世話になったサイト

 有用なソフトウェアおよび貴重な情報をご提供頂いている皆様に、お礼申し上げます。(以下、順不同)

 参考サイト(1):mikan++>TOPPERS>FatFsの移植


 更新履歴

 2012.03.21 「今後の課題」にリンクを追加。
 2009.12.15 「考察」に追記を追加。
 2009.12.12 新規作成


[Home]  [MacSoft]  [Donation]  [History]