技術コラム集

RX62NとSH7672内蔵USBホストドライバの特徴と実際

ユークエスト株式会社
佐々木 哲(ささき さとし)

 

7.RX62Nの機能を活用したWAVファイルの再生

USBメモリがつながるようになったので、少し応用事例を紹介します。

RX62NにはSH2A(SH7262)の様な高機能なオーディオ出力はありませんが、10bitのDACが搭載されており拡張基板WKLCD-62Nを使用すると簡単にステレオオーディオ出力が実現できます。この機能を用いてUSBメモリに保存されたWAVファイルを再生することにします。(写真2)

写真2.WKLCD-62Nを使用して、オーディオスピーカとUSBメモリをつないだ様子
写真2.WKLCD-62Nを使用して、オーディオスピーカとUSBメモリをつないだ様子

USBメモリのコピーでは、ファイルシステムを使用せずに稼働させましたが、今度はファイルを扱うためにファイルシステムが必要です。

MatrixQuestFs/fatを使用すればコンパイルしてMatrixQuestUSBにリンクするだけで容易に実現できますが、今回はInterface誌でおなじみのfatFsをMatrixQuestUSBにポーティングしてみることにします。今回の構成は図5の様になります。

図5.WAVファイル再生プログラムの構成


7-1.fatFsとMatrixQuestUSBの接続

移植に必要となる最小限のユーザ作成関数は、disk_initialize() disk_status() disk_read()ですが、サンプルにはdisk_write() disk_ioctl()を合わせて実装しています。

全関数共通の仕様として、サポートドライブは一つとしますので、各関数の引数Driveは0のみ有効です。

・disk_initialize()
ディスク・ドライブを初期化する関数です。USBの初期化はあらかじめ別途行う事としますので、ここではフラグ STA_NOINIT をクリアします。

・disk_status()
ディスク・ドライブの状態を取得する関数です。戻り値と今回のサンプルの関連については以下の表を参照してください。(表4)

STA_NOINIT ドライブが初期化されていないことを示すフラグ。
システム・リセットやメディアの取り外し等でセットされ、disk_initialize() の正常終了でクリア、失敗でセットされます。
STA_NODISK メディアがセットされていないことを示すフラグ。
このバージョンではUSBメモリの有無を示します。
USBカードリーダなどでメディアが無い場合でもこのフラグはクリアされますので、使用できません。
STA_PROTECTED メディアがライト・プロテクトされていることを示すフラグ。
常にクリアされています。

表4. disk_statusが示す状態とUSBの状態の対応


・disk_read()
ディスクからセクタを読み出す関数です。若干の型変換が必要なことを除けばそのまま渡すことができます。
usblBlkRd(usblFatFsInfo.pUsblBlk,(UINT)SectorNumber,(UINT)SctorCount,Buffer);

・disk_write()
ディスクにデータを書き込む関数です。disk_read()同様若干の型変換が必要なことを除けばそのまま渡すことができます。
usblBlkWrt(usblFatFsInfo.pUsblBlk,(UINT)SectorNumber,(UINT)SectorCount,Buffer);

・disk_ioctl()
ディスク・ドライブ自体に対する様々な制御をします。今回はfatFsのサンプルffsample.zipで実装を求められているCTRL_SYNC GET_SECTOR_SIZE GET_SECTOR_COUNT GET_BLOCK_SIZE CTRL_ERASE_SECTOR を実装します。実際にはほとんど何もする必要はありません。(表5)

コマンド 解説 戻り値 Bufferの値
CTRL_SYNC ディスクへの書き込みを完了します。USBドライバの場合、SYNCで何等かの処理が必要な場合はありません。 RES_OK N/A
GET_SECTOR_SIZE それぞれの情報はMSCのクラスドライバで取得して保持しています。この情報が必要となるのは(_USE_MKFS == 1)の場合のみですから、今回は非対応としています。 RES_PARERR N/A
GET_SECTOR_COUNT RES_PARERR N/A
GET_BLOCK_SIZE サンプルでは固定値を返します。 RES_OK 512
CTRL_ERASE_SECTOR フラッシュ・メモリ用ということですので、USBホストドライバについては無関係ですので、常にOを返します。 RES_OK N/A

表5. disk_ioctlのコマンド対応一覧

たった上記の実装だけでfatFsを使用してUSBメモリのファイルにアクセスできるようになります。


7-2.オーディオ再生にDMACAを使用

WAVファイルには、オーディオデータの情報が先頭に記録されており、その後ろにPCMオーディオデータが保存されています。

PCMデータの詳細については、WebサイトTechVillage(http://www.kumikomi.net/archives/2010/07/ep22onse.php)に解説記事が掲載されていますので一読すると良いでしょう。

ディジタルオーディオの出力を確実に行うためにはDAコンバータに対して決められた周期でオーディオデータを出力する必要があります。ご存知の通り、一般的なCDは44.1kHz/16bit/STEREOでサンプリングされています。このデータを滞りなく再生するためにはUSBメモリから読みだすレートを計算すると…

44.1kHz x 16bit x 2ch = 1,411,200bit/sec ≒ 1.35Mbit/sec

となり、約1.35Mbpsのビットレートが必要になります。RX62N内蔵USBを使用する場合、USBはFullSpeedになりますが、MatrixQuestUSBを使用すれば、ビットレートとしては問題になりません。

ただ、このビットレートを保持しながら44.1kHz≒22.7μsecの間隔でオーディオデータをDACに転送する必要があります。

Interface誌2011年6月号の「オープン・ソースMP3デコーダを使ったMP3プレーヤの制作」ではCMTのタイムアウトによる割込みを利用していましたが、RTOSを使用する環境では22.7μsec間隔での割込みは負担になります。

RX62NではCMTの割込みをDMAの転送開始トリガにすることができますので、DACへのオーディオデータの転送をCMTの割込みをDMAコントローラ(以下DMAC)に対するトリガとして発行し、DMACがDACにデータを転送する事でオーディオ出力を実現してみます。DMACの設定はDMAフリーランノーマル転送モードと拡張リピートモードを組み合わせて使用し再生を実現することで、確実なオーディオ再生と安定したUSBの稼働を実現します。(図6)

図6.DMAを活用したUSBメモリWAVファイルの再生

ただ、このモードには一つだけ欠点があります。DMAの転送先をDACに設定しますが、拡張リピートモードでLch/Rchの順にトリガ毎に転送します。片方のチャンネルを44.1kHzで再生するためには88.2kHzの周波数で左右毎に転送する必要があります。この場合、Lchに対してRchは11.3μsec遅れて再生されることになります。

今回はあくまでUSBを使う事が本来の目標ですので、ここは目を瞑ることにしましょう。


7-3.オーディオ再生処理の流れ

バッファはコンパイル時にオーディオ再生データ保存用に設定したセクションを使用することにします。 このバッファをA面、B面に分けてダブルバッファとして考えます。つまり、B面を再生中にA面にUSBメモリからのデータを読み込んで、A面再生中にB面を読むという順序になります。

そのほか、以下のような流れです。

1.初期化
2.USBメモリ認識
3.USBメモリ内ファイルのOPEN
4.WAVヘッダ読み捨て
5.A面B面データ読み込み=>0x8000を全データに加算
6.DMA開始
7.A面再生完了待ち
8.A面データ読込み
8-1.詠み込んだデータに0x8000を加算
9.B面再生完了待ち
10.B面データ読込み
10-1.詠み込んだデータに0x8000を加算
11.8または10で終了と判断しなければ7へ
12.終了

7,9では、それぞれ再生(DMACによるDACへのデータ転送)の完了を待ちます。これはDMACの転送元レジスタのアドレスが何処を処理しているかで判断できます。

8-1,10-1では、USBメモリから読みだしたデータに0x8000を加算しています。これはWAVファイル内のデータが2の補数形式で保存されているのに対して、RX62Nでは整数値で扱うことに起因します。例えば、16bitデータの場合、WAVファイルのデータがとりうる値の範囲は符号付きで0x7fff〜0x8000ですがDACは0x0000〜0xffff(ただし上位10bitが有効)となりますので、WAVファイルのデータをそのままDACに書き込んでもうまくいきません。そこで、WAVファイルから読みだしたデータに対して0x8000を加算して整合性がとれるようにしています。

サンプルプログラムの具体的な使用方法はプロジェクト内のreadme.txtを参照してください。


7-4.DMACの初期化

以下の様に各レジスタを設定します。

SYSTEM.MSTPCRA.BIT.MSTPA28 = 0;      /* スタンバイ解除 */
DMAC0.DMCNT.BIT.DTE = 0;            /* 割込み禁止 */

ICU.DMRSR0= 30;                   /* 起動要因の選択 CMT2の割込みとつなぐ */

DMAC0.DMSAR = (void *)buffptr[0];        /* バッファのアドレス */
DMAC0.DMDAR = (void *)0x000880C0;      /* DACのアドレス */
DMAC0.DMTMD.BIT.DCTG = 1;           /* 周辺モジュールからの割込み */
DMAC0.DMTMD.BIT.SZ = 1;             /* データ転送サイズビット */
DMAC0.DMTMD.BIT.DTS = 2;            /* リピート・ブロック設定しない */
DMAC0.DMTMD.BIT.MD = 0;            /* ノーマル転送 */
DMAC0.DMCRA = 0x0000;             /* ノーマル転送なので0x0000を指定 */
DMAC0.DMINT.BYTE = 0;              /* 割込みは使用しないので0x0000を設定 */
DMAC0.DMAMD.BIT.DARA = 2;           /* 2bytesの繰り返し */
DMAC0.DMAMD.BIT.DM = 2;            /* インクリメント */
DMAC0.DMAMD.BIT.SARA = 0xB;         /* 2kbytesの繰り返し */
DMAC0.DMAMD.BIT.SM = 2;            /* インクリメント */

DMAC0.DMREQ.BYTE = 0;              /* 使用しない */
DMAC0.DMSTS.BYTE = 0;              /* 使用しない */
DMAC0.DMCNT.BIT.DTE = 0;            /* 初期値は禁止 */

DMAC0.DMCSL.BIT.DISEL = 0;           /* CPUへは割込みしない */

DMAC.DMAST.BIT.DMST =1;            /* DMACA起動を許可 */
DMAC0.DMCNT.BIT.DTE = 1;            /* 割込み許可 */


7-5.CMTの初期化

以下の様に各レジスタを設定します。

SYSTEM.MSTPCRA.BIT.MSTPA14 = 0;     /* スタンバイ解除 */
CMT2.CMCR.BIT.CKS = 0;             /* PCLK/8を供給 */
CMT2.CMCR.BIT.CMIE = 1;            /* コンペアマッチ割込み許可 */
CMT2.CMCOR = 68;                 /* 約88.2kHzの周波数 */


7-6.DACの初期化

以下の様に各レジスタを設定します。

SYSTEM.MSTPCRA.BIT.MSTPA19 = 0;     /* DAスタンバイ解除 */
PORT0.DDR.BIT.B3 = 0;               /* DA0出力使用 */
PORT0.DDR.BIT.B5 = 0;              /* DA1出力使用 */
DA.DADR0 = 0x8000;                /* 初期値zeroに設定 */
DA.DADR1 = 0x8000;                /* 初期値zeroに設定 */
DA.DADPR.BIT.DPSEL = 1;            /* MSB詰め */
DA.DACR.BYTE = 0xFF;              /* D-A変換開始 */


7-7.DMAの開始

以下の設定でDMAが開始されます。

CMT.CMSTR1.BIT.STR2 = 1;         /* カウント開始 */
ICU.IER[03].BIT.IEN6 = 1;            /* 割込み許可 */


7-8.応用

このサンプルプログラムではUSBメモリへのアクセスが本来の目的ですので、オーディオ再生プログラムとしては未完成です。たとえば以下の様な応用が考えられます。

・マクロ定義で固定しているファイル名をディレクトリ内の一覧から選択、または、順次再生する。
・44.1kHz,16bit,Stereoに固定しているWAV仕様をWAVヘッダの解析を行い、各設定を動的に反映する。
・基板上のSWやタッチパネルと連携して再生、早送り、曲スキップなどの機能を加える。
・LCDを活用して曲イメージに合わせた画像やレベルメータを表示する。
・Interface誌、2011年6月号に掲載されているMP3デコーダを実装してUSBメモリプレーヤーに仕立てる。

など、応用は多彩です。

また、MatrixQuestUSBとfatFsのインターフェース部分はRX62NでもSH2A(SH7262)でも同じですから、USBメモリのコピーで用いたMatrixQuestUSB/lite SH7262版にfatFsを実装する方法はRX62Nと全く同じです。メモリも大容量ですからミドルウェアを使用するメリットを活かして是非実装してみてください。

また、今回のサンプルでは極力プログラムを簡素化するためにRTOSのシステムコールを使わない様にしています。NORTiとMatrixQuestUSB/ex(廉価版)を導入するとNORTiのシステムコールを使って高機能なアプリケーションを開発することもできます。

 

8.サンプルプログラムのダウンロード

雑誌『Interface』のダウンロードページへ
   http://www.cqpub.co.jp/interface/download/contents.htm

2011年8月号 USB機器開発トラの巻!の「特集 第5章 USBメモリ内容コピー&WAVE再生プログラムの作成」から、RX62N用サンプルプログラムと、SH-2A用サンプル・プログラムがダウンロードできます。

 

参考文献
CQ出版社:Interface 2010年6月号 第1章 付属SH2Aマイコン基板の使い方
CQ出版社:Interface 2010年7月号 第4章 3.デバイス接続検知とバス・リセット
CQ出版社:Interface 2010年9月号 第3章 FATファイル・システムの詳細
CQ出版社:Interface 2011年5月号 Prologue 付属RX62Nマイコン基板の応用事例
CQ出版社:Interface 2011年6月号 第4章 オープン・ソースMP3デコーダを使ったMP3プレーヤの制作
ルネサスエレクトロニクス:SH7262 グループ、SH7264 グループハードウェアマニュアル
ルネサスエレクトロニクス:RX62Nグループ、RX621グループ ユーザーズマニュアル ハードウェア編
ルネサスエレクトロニクス:R8A66597FP/DFP/BG ASSP (USB2.0 2Port Host/1Port Peripheral Controller):
ミスポ:μITRON仕様準拠リアルタイムOS NORTi version4 カーネル編 ユーザーズガイド
ユークエスト:MatrixQuestUSB/lite USBホストドライバ ユーザーズガイド
ユークエスト:MatrixQuestUSB/lite Mass Storage クラスドライバ ユーザーズガイド
ユークエスト:MatrixQuest ミドルウェア共通環境 プログラマーズ・ガイド

 

関連情報

MatrixQuestUSB/host
USB1.1/2.0対応ホストドライバ プロトコルスタック
MatrixQuestUSB/lite
組込みコントローラ用USBホストドライバプロトコルスタック
MatrixQuestUSB/ex
マスストレージ機能専用USBホストドライバ

このページの上へ