マイコン工作実験日記

Microcontroller を用いての工作、実験記録

音声出力とキーパッド検出の同時処理

2008-03-12 23:22:27 | W-SIM
音声出力ができたので、W-SIMからのPCM信号を出力するようにしてみました。つまり、通話先からの音声をUSB電話機から出力できるようになりました。ここまでは、好調だったので、並行してキーパッドの検出もできるようにコードを追加してみました。音声出力のためのIso-Out転送は1ms毎に起動されますが、これに加えてコマンド送出のためのControl転送と、キー状態読み取りのためのInterrupt転送を追加してみたのです。ところが、音声出力がブツブツと切れるようになってしまいました。

どうやら、Iso-Out転送に続いてCotrol転送を実行していると1msを超えてしまい、次の周期の音声が正しく送出できなくなってしまっているようです。Control転送は、SETUP, DATA, STATUSの3つのステージから成りますが、これらを連続して実行するには無理があるようです。各ステージの間にIso転送をはさむように処理するように書き換えることにします。

USB-P4K 音声出力

2008-03-10 23:54:01 | W-SIM
USB-P4Kへの音声出力を試してみました。

本来であれば、USBホストはデバイスから送られてきたConfiguration Descriptorを解析して、スピーカとして使われるインタフェースを見つけて、それを活性化してやる処理が必要となります。しかし、電話機としてはUSB-P4Kしか使うつもりありませんから、こういう面倒な処理はバッサリと省略することにします。出力先インタフェースは、Interface #2, Alt #1で決め打ちです。これと対応するEP番号も、4番として固定してしまいます。

音声出力はIso転送になるので、MAX3421からFRAME割り込みがかかるのを待って、1msのタイミングをとってみました。以前使ったHello Worldの音声を送ってみると、比較的簡単に音がでました。音量調節も何もしていないのですが、とりあえず音が出てくれたので助かりました。

とりあえずの試験は問題無いようですが、最終的には音声出力だけではなく音声入力も処理してW-SIMと送受しなければなりませんし、キーパッドとLCD表示の処理も必要となります。順次、処理を追加しながら動作を確認していくことにします。

USB-P4K LCDへの表示

2008-03-09 19:06:30 | W-SIM
キーの検出につづいて、LCDへの表示方法についてもLinuxのドライバを読んで確認しました。

LCDへの表示もキーの検出と同じようにクラス特有のSET_CONFIGURATIONをインタフェース3番に対して送ってやることで実現されます。キーの場合と違って、インタラプト転送で応答が返ってくることは無いようです。

LCDへの表示はデータパケット中でCMD_LCDというコードを指定してSET_CONFIGURATIONを送ります。表示データとしては、点灯/消灯させたいLCDセグメントをビットマップで指定します。その結果、1のビットが点灯され、0のビットが消灯されるという仕組みのようです。

LCD表示装置がもつセグメント数は全部で160セグメントほどあり、それを24バイト分のビットマップで表現するようになっています。SET_CONFIGURATIONで送れるデータパケットの長さは16バイトですが、表示データとして有効な部分は11バイト分しかありません。そのため、全部のセグメントの表示を変更するためには、CMD_LCDを複数回送る必要があります。データパケットには、データの長さとオフセットを持てるようになっており、LCDのどの部分からの変更データかを指定することができるようになっています。



とりあえず、全セグメントを点灯してみる試験をした結果が上の画像です。Linuxのドライバではどういうわけか、V-STORE, V-DIAL, 鍵, MAILの4つのアイコン表示はサポートされていません。OEM先によって、ハードウェアにいくつかのレビジョンがあり、LCD表示機能に違いがあるのかもしれません。

ともかくも、LCD表示の仕方は理解できましたので、ドライバを書き始めることにしようと思います。


USB-P4K キーの検出

2008-03-07 22:25:46 | W-SIM
USB電話機 P4Kでのキーの検出について調べました。

Linuxのドライバのソースを読んだところ、普通のマウスやキーボードとはずいぶんと使い方が異なっていることが判明しました。普通はインタラプト転送で、定期的にEPを読んでやれば、キーやマウスの状態を読み取ることができます。しかし、USB-P4Kでは、コントロール転送とインタラプト転送を組み合わせて使うようになっているようです。

まず最初にコントロール転送により、HIDインタフェースである3番のインタフェースに対して、動作指示内容をデータパケットとするクラス特有のSET CONFIGURATIONを送信してやります。その後、インタラプト転送で3番のインタフェースに割り当てられたEPである1番を読み出すと、その結果レポートが返るという仕組みになっています。動作指示データは、16バイト長であり、インタラプト転送で返されるレポートも同じフォーマットの16バイト長となっています。


キー検出については、キー状態変化検出と、スキャンコードへの変換の2段階の処理を経て、どのキーが押されたかを知ることができます。
  1. まずCMD_KEYPRESSをコントロール転送で送ると、次のインタラプト転送では、その結果としてキー状態のシーケンス番号が返ってきます。連続してCMD_KEYPRESSを送信し、シーケンス番号が変化したことによりキー状態に変化が生じたことを知ることができます。
  2. 次に、シーケンス番号を引数としてCMD_SCANCODEをコントロール転送で送ります。すると、インタラプト転送ではシーケンス番号をキーのスキャンコードに変換してものが返ってきます。これで、どのキーが押されたかがわかります。キーが離された場合には、スキャンコードとして0xFFが返ってきます。
フックスイッチの状態については、CMD_KEYPRESSでは検出できないようです。別にCMD_HOOKPRESSが用意されており、このコマンドを送信する必要があります。ただし、このコマンドでフックスイッチの状態が判別できるので、SCANCODEへの変換の必要はありません。ちょっと面倒ですが、フックスイッチだけキーボドマトリックスの上に載っていないんでしょうかね。

したがい、キーを検出するためには、インタラプト転送の周期(20ms)に先立ち、コントロール転送でCMD_KEYPRESSとCMD_HOOKPRESSを交互に送信し、状態変化を見張るというのが、この電話機の使い方のようです。

LCDへの表示も、コントロール転送でコマンドパケットを送信してやることで実現しているようです。詳しくは、この次に調べることにします。

前回の記事でSPIのクロックについて言及するのを忘れていました。MAX3421EはSPIクロックとして26MHzまで使えるという仕様になっています。AT91SAM7S256ではMCKが48MHzになっているので、これを半分にした24MHzをSPIクロック(SCLK)としてMAX3421Eに供給してみたのですが、うまく動いてくれません。3分して16MHzにすると安定して動いてくれるようです。配線の引き廻しがまずくて波形が乱れちゃっているのかもしれません。

SetConfigurationまで動作

2008-03-05 23:26:54 | W-SIM
MAX3421Eを使ってのUSBホストのドライバを書き始めました。

改めためてデータシートを見てみると、現在のチップのリビジョンは3になっており、初期のバグがいくつか修正されているようです。REVISIONレジスタを読み出して確認してみましたが、わたしの手持ちのチップはレビジョン1でした。買ったのが2年ほど前なので、発売から日が浅かったということですね。ホスト側機能のバグは、ドライバで回避可能なようなので、それで対応することにしましょう。

APPLICATION NOTE 3936にホストドライバの基本部分についてのサンプルコードと説明がありましたので、こいつを拝借することにしました。AT91SAM7S用に書き換えて、SetConfigurationするところまで動かせるようになりました。まだ、割り込みにおかしいところがあるようで、ちゃんと動作してくれないこともあります。
電話機を挿した際には、Device Descriptorと Configuraiton Descriptorが読み込まれ、次のようなログが出力されます。



Config Descriptorの内容を整理すると、どうやら次のようにインタフェースが使われているようです。

InterfaceAlternateEP (転送方式)用途
00N/A音量制御
10N/Aマイク(非活性化時)
112 (Iso 入力)マイク(活性化時)
20N/Aスピーカ(非活性化時)
214 (Iso 出力)スピーカ(活性化時)
301 (Inter 入力)キーパッド


インタフェース番号3は、インタラプト転送で入力になっているので、キーパッド入力に使われると思われます。LCD表示制御用には独立したEPが用意されていないようなので、別途なんらかの仕掛けがあるはずです。この点については、Linuxのドライバを読んで調べることにします。



どうやら、USB P4-KはSetConfigurationを受けると、LCDにVOIP-PHONEと表示してくれるようです。マイコン側の制御で表示しているわけではありません。7セグメントでのアルファベット表示に郷愁を感じますねぇ。


USB-P4K

2008-03-03 23:42:38 | W-SIM
USB電話機として使用するのは、YealinkのUSB-P4Kです。どんなUSB電話機でもつながるというのは結構大変な作業になるので、この電話機で決め打ちにしてしまいます。実は、この電話機を選択しているのには、それなりの理由があります。



まず第一の理由はLinuxで使えることです。Yealinkの電話機は、Linux上ではYealinkドライバとしてサポートされており、P4-K用のパッチも存在します。そのため、ソースを読めばキーの判別やLCDへの表示方法がわかるはずです。もともと、Linuxで使えるということを知って、しばらく前に買ったのですが、最近はあまり店頭では見かけないようです。USB電話機では、送受話器としての機能は、USBのスピーカとマイクとして提供されますので、どんな電話機でも細かい仕様に違いはあっても基本的なインタフェースはUSB標準に合致したものになっています。ところが、キーパッドや表示機能については各ベンダが勝手に作りこみをしているので、通常はベンダの提供するドライバが必要となります。マイコン工作用にドライバを提供してくれるベンダなんていませんので、Linux用のソースがあるというのは、大変助かります。

ふたつめの理由は、サンプリングレートが8KHzであることです。普通のUSBスピーカではCDクオリティは必須ですので、サンプリングレートも44.1KHzとか48KHz, 96KHzになっています。USB電話機でも、同じような部品を使って作られているのかどうか知りませんが、サンプリングレートとして44.1KHz/48KHzをサポートしているものが多いようです。電話機のサンプリングレートが高くても、W-SIMが送受できるのは所詮8KHzです。そのため、スピーカやマイクのレートが8KHzでない場合には、マイコンでレートの変換をしてやらねばならないことになってしまいます。サンプリングレートがW-SIMと同じ8KHzであれば、レート変換作業が不要になって助かるのです。複数のサンプリングレートをサポートできる場合には、レートとしてどれを使用するかの選択も必要になりますが、P4-Kは8KHzしかサポートしませんので、その必要もありません。

Skypeのことはよく知りませんが、音声として8KHz以上の帯域を使う音質の高い音声コーデックを使うことができれるのであれば、このYealinkの電話機は、Skype通話における音質の面ではダメダメな電話機ということになります。しかし、W-SIMとつなげて使うマイコン工作には、最適な電話機です。

もうひとつの理由は、外見も普通の電話機チックにできており、スピーカフォン機能もあることです。LCD表示機能があるので、発信者番号や通話時間を表示することもできます。Skypeで使うのであれば、これらの情報はPC上に表示できるので、電話機にはLCDが無くても困らないでしょうが、Skype無しで電話機単体で使うにはLCD表示は必須です。もっとも、それらの機能をちゃんと使えるようにするためには、マイコンでちゃんと制御してやらねばならないのですが。。。

USBホストを追加した

2008-03-01 17:17:43 | W-SIM
USB電話機を接続するための基板を作ってみました。



「作った」といっても、基板自体はRev.2ボードの流用です。USBホスト機能を実現するためのチップとしてMAX3421Eをボード上に追加しただけです。写真右下部分が今回追加した部分であり、右下のタイプAコネクタにUSB電話機をつなげることになります。

USBホストのチップとしては、なんと言っても秋月で買えるSL811HSTが入手しやすいのですが、こいつは8bitのデータバスで接続するようになっていますので、外部メモリを使えるマイコン向けです。AT91SAM7Sでは、外部メモリを接続することができないので、GPIOで制御することになってしまい面倒です。一方、MAX3421Eは、SPIでつなぐことができるので、ほとんどのマイコンと簡単に接続できちゃいます。追加部品も、DP/DMに入れる抵抗2本とパスコン程度で済みますので工作も簡単です。動作クロックとしては12MHzが必要ですが、幸いなことにAT91SAM7SのPLLを96MHzに設定すれば(この使い方が標準ですが)、これを分周してPCK0から12MHzを出力できます。そのため水晶発振器を追加する必要もなくなりました。

このように書くと、MAX3421Eを選択したもっともらしい理由のようですが、実際のところは2年程前に、おもしろそうだと思って買っておいて死蔵したままになっていたことを思い出して、引っ張り出しただけです。当面CPUボードへのUSB給電で動かしますが、ACアダプタ用のジャックを付けてもいいかもしれません。

とりあえずは、MAX3421Eの内部レジスタを読み書きできることだけは確認できました。当初、どのレジスタを読み出しても0xFFになってしまっていて、あせりました。原因は、リセット直後はMAX3421Eは半2重のモードで動作していたこと。そのため、MISO線は使用されずにHZになっていたために、0xFFと読めたようです。まず最初にPINCTLレジスタを変更することで、全2重通信のモードにしてやる必要ありでした。