マイコン工作実験日記

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

RTP動作の確認

2008-08-29 07:08:40 | VoIP
前回は両方向のRTPの流れをWireSharkを使って調べてみました。この方法で、VoIP GWから20ms間隔でRTPが流れていることは確認できましたが、X-Liteから送られたRTPをVoIP GWがちゃんと受信できているかどうかまではわかりません。そこで、VoIP GW側のRTP送受信タスクで、パケット数をカウントしてみました。およそ5分間の通話状態でのカウントは次のようになりました。



毎秒50パケットですから5分間では15000パケットになるはずです。outpacketはほぼ期待どおりの数字です。しかし、inpacketがoutpacketに比べてずいぶんと少ないようです。「ひょっとして、VoIP GWが受信パケットを取りこぼしているのではないだろうか?」と思いました。受信タスク自体は読み捨てているだけで何の処理もしていないので負荷は小さいはずですが、ドライバやTINETのレベルで取りこぼしが発生する可能性もあります。

RTPでは各パケットにシーケンス番号が付いていますので、これが非連続になれば取りこぼしがあったことがわかります。それを確認してみたのが、上記表示の "bad seq" の値です。シーケンス番号が非連続のパケットを受信する度にインクリメントされるのですが、結果はゼロ。つまり、とりこぼしはなかったことになります。

そうすると、残る可能性はX-Liteのパケット送信間隔が長いために、結果として送信パケット数が少なくなったことになります。上記の数字はいつも開発に使っているLet's NoteでX-Liteを走らせた場合の数字なのですが、デスクトップのマシンでもX-Liteを走らせてみました。結果は、次のとおり。inpacketとoutpacketの値がほぼ同じとなりました。



どうやら、Let's NoteでX-Liteを走らせた場合にはパケット送信数がホントに少なかったようです。デスクトップもLet's Noteも OSとしてはWindows XPを使っています。Let's Note上では時間がゆっくりと流れているんでしょうかねぇ。in と outで380パケットも差があるということは、時間にしておよそ7.6秒に相当します。5分(300秒)間で7.6秒もずれてきてしまうとは驚きです。

RTPを両方向にする

2008-08-26 00:37:26 | VoIP
今度は、呼を接続状態までもっていき、RTPを両方向に流すことにします。想定するフローは次のとおりです。SIP的には一般的な発呼/切断シーケンスですが、PHS電話網とつなぐ場合にはALERTよりもPROGRが返ってきて、網からのRBTを聞く動作が多く、180 Ringingではなくて183 Session Progressになるようです。今回の実験ではX-Liteに呼び出し音を鳴らしてもらうために、180を使うことにしました。

180に続いて、200 OKにSDPを付けて返すことにより、呼が接続されます。X-LiteからもRTPが送られてきますので、これを受信して読み捨てるだけのRTP受信タスクも用意しました。切断手順も、今度はCANCELではなくてBYEのリクエストが来るようになるので、これを受けられるように機能追加です。RTPの送受信タスクはBYEを受けた時に終了させます。これらの変更でどうにか接続/切断できるようになりました。接続時のX-Lite画面はこんな感じです。



じつは200 OKを返してもACKがX-Liteから返ってこないという問題が発生して、ハマッテしまいました。X-LiteはRTPを送ってきたので、200 OKが届いることは確かなのにACKが返ってこないという症状でした。X-Lite側で動作のデバックログを採る機能があり、そのログを調べたところ、X-Liteでは確かにACKを作成して それを送信しようとしていたのですが、その送り先が自分自身になっていることが判明しました。200 OKの内容をよくよく調べてみたら、Contactヘッダで設定しているアドレスが間違ってX-Lite側のアドレスになってしまっているのが原因でした。

動作確認のため、WireSharkでパケットをキャプチャしてみました。WireSharkではVoIP関連機能が充実しているので、以下で簡単に紹介しておこうと思います。まず、VoIP解析してグラフを描かせてみると、バッチリRTPの流れた時間まで表示してくれます。良くできてますねぇ。



RTPの再生機能も用意されています。下図の例では上側がVoIP GWからの音声でいつもの"Hello World"を繰り返し流しています。下側はX-Liteからの音声ですが、マイクつなげていない状態なので何も載っていません。単なる再生だけなら、それほどたいした機能でもありませんが、Jitter Bufferサイズの変更ができるようになっているところがシャレています。バッファサイズを小さくすると、どのていどパケットを落としてしまうかがシュミレーションできるようです。



RTPの解析機能も用意されています。上りと下りそれぞれの方向でのパケット送出間隔のゆらぎ(ジッタ)の変化を調べられ、それをグラフ化することもできるようになっています。



上の表示はVoIP GWが送出しているRTPです。パケットの間隔がほぼ20ms間隔で安定しており、ジッタが小さく抑えられていることが確認できます。一方、下の表示はX-Liteが送出しているRTPです。3ms程度のジッタがあることがわかります。わたしのPCの処理速度が遅いのか、Windows XPのタスクのスケジューリングの都合なのか、それともX-Liteの実装の都合なのかはわかりませんが、3ms程度であれば何の問題もないでしょう。


RTPを流してみる

2008-08-23 00:47:15 | VoIP
前回は呼制御信号だけを使って呼び出し音を鳴らしました。今回は、フローをちょっとだけ変えて、下図のように網側からのトーキーを流すシーケンスを想定してみます。通話相手とはまだつながっていない状態ですが、網からは音声が流れてくるので、これをRTPにしてSIPクライアントに送ることになります。

依然としてW-SIMはまだつながっていないので、前回と同様シーケンスの右半分はソフトウェアで疑似的に実現しています。前回180 Ringingだった箇所が183 Session Progressに代っているわけですが、今回はRTPを流すために、RTPで使用するポート番号を指定するSDPを付け加えています。また、とりあえず音声は片方向だけでいいだろうということで、a=sendonly をSDPの中で指定しています。

183で指定するポート番号は、VoIP GW側で使用するポート番号ですが、20002を固定で使うことにします。相手側のポート番号は<storong>INVITEに含まれているSDPの中に記述されていますので、この解析処理を追加してやりました。そして、183の送出とともにRTPを送信するタスクを起動してやります。送信する音声データは、これまでも試験目的でしばしば使っている"Hello World"です。

まだ呼がつながる前の状態ですので、X-Lite側でオンフックするとCANCELが送られてきます。これを受けてRTPの送信タスクを終了しています。

X-Liteの画面ではトーキーが流れている間、次のように "Calling"と表示されました。RTPはTOPPERSの周期ハンドラの機能を使って20ms間隔で送信していますが、10分くらい放置しても継続して動作しているので、Ethernetの送信ドライバまで問題なく動作しているようです。


呼出し音の確認

2008-08-19 23:09:26 | VoIP
SIPクライアントの登録ができたので、次のステップとして発呼の処理にとりかかっています。とは言っても、ハード的にはまだW-SIMすらつながっていないので、当然ながら実際に発呼することはできません。そこでW-SIMのモデム動作をソフトで疑似的に実現してやることで、SIPのプロトコル処理部分の実装とその動作確認作業を進めることにします。

今回、実装と試験を進めるのは、発呼、呼び出しと接続前の切断動作です。相手の呼び出し(ALERT)が確認できた後に、相手が応答する前に発呼側から切断するというシナリオに相当します。下図のようなシーケンスを想定します。

  • クライアントからの発呼動作によって生成されるINVITEを受けて、本来であればW-SIMからの発呼動作をすべきところですが、W-SIMがないので疑似モデムタスクにATDTメッセージを送って、100 Tryingを返すことにします。
  • 疑似モデムタスクは、ATDTメッセージの受信から500ms後にALERTイベントを生成します。これを受けてVoIP GWは180 Ringingをクライアントに送ります。
  • クライアントからの切断操作によって生成されるCANCELを受けたら、疑似モデムタスクにATHメッセージを送って、クライアントには200 OKを送り返します。
  • 疑似モデムタスクはATHの受信から500ms後にOKイベントを生成します。
  • VoIP GWはOKを受けて、クライアントには487を送信します。
  • クライアントは200 OKを返してダイアログが終了します。

今のところ上記フローを実現するために必要な状態遷移表しか用意していません。実験したい手順に応じた状態遷移を順次追加していくことで、だんだんと完成度を高めていくことにします。

現段階ではRTPは全く実装できていないので音声の送受はできません。そのため、上記シーケンスでもINVITEの持つSDPの内容については全く見ていません。しかしながら、180 Ringingをクライアントが受信した時点で、クライアントソフトが自分で呼出し音を生成して流すことができれば、それを確認することができるはずです。X-Liteで試験したところ、次の画面のようになりました。



54321がダイアルした番号です。"Ringing..."という表示とともにめでたくPCのスピーカから呼び出し音が流れだしました。画面右に緑色のインジケータが縦に並んでいますが、呼び出し音に応じてこの表示が上下しました。切断手順も動いているようです。うーん、なんとなく "らしく" なってきました。


SIPを作り始める -- 登録まで

2008-08-17 23:17:28 | VoIP
VoIP GWを目指してSIPサーバの実装を開始しました。SIPの基本的なシーケンスについては、RFC3665に整理されているようですが、この内容を整理したWebページがあるので、これを参照しながらコードを書いていくことにしました。

まず最初に必要な機能は端末の登録(REGISTER)処理です。登録さえ受け付けてやれば、SIPのクライアントはサーバと接続したと認識してくれるはずです。サンプルのシーケンスでは、サーバ側が認証を要求しているためにいったん401を返しており、端末が認証ヘッダを付加して再度REGISTERを送信する流れになっています。自作VoIP GWでは端末認証はあっさり省略することにします。REGISTERの要求を無条件に受け付けて200 OKを返してやればいいでしょう。いちおう、expiresパラメータとExpiresヘッダだけは確認して、登録の設定/更新なのか解除なのかの判別だけはすることにします。他にもViaとか To, Fromとかのヘッダが付いてますが、要はREGISTERに付いてきたヘッダをほとんどオウム返しに付けてやればいいようです。ただし、Toには自分側のtagを追加して返します。

それでは早速テストです。SIPのクライアントとしては、Counter PathのX-Liteを使うことにします。X-Liteを選択した特別な理由があるわけではありません。単にフリーでダウンロードできる良く知られたクライアントらしく思われただけです。

X-LiteのSIP account設定画面では、次のようにパラメータを設定しました。



DomainはMake ControllerのIPアドレスです。まだDHCPクライアント機能も実装していませんので、IPアドレスはプログラム中に hard codedしてあり、設定/変更することすらできません。Passwordとか Authorization user nameとかのパラメータは、認証関連でしょうから設定しなくてもいいのでしょうが、全てuser nameと同じにしておきました。

OKを押すと、めでたく画面にReadyが表示されました。登録できたようです。まだまだ通話できるまでには先は長いのですが、SIP的には最初の一歩が動いたということで、ちょっと嬉しいですね。実際にはパケットが一往復しているだけなんですけど。



Wiresharkでパケットを確認してみたところ、X-LiteはREGISTERに続いてSUBSCRIBEも出していました。調べてみるとRFC3842で規定されている「メッセージあり表示」の通知(Notify)のためのもののようです。VoIP GWではサポートしないので、501 Not Imprementedを返すことにしました。下図は、結果のフローをWiresharkのグラフ化機能を用いて表示したものです。


MMnetSAM7x

2008-08-16 01:26:35 | Weblog
先日AT91SAM7Xのボードを選択する際に、PropoxのMMsam7xと比較した結果としてMake Controllerを選択したのですが、そのPropoxから新たにMMnetSAM7xが発売になったようです。こいつは、ちゃんとPHYチップとRJ45が基板に載っています。余計な物が載っていない、こういうヘッダボードが欲しかったんです。3.3Vのレギュレータすら載っていないのはちょっと残念ですけど。

と、いうわけでとりあえずポチッとしてみました。まだ英文マニュアルすらないようですが、回路図あるんでさほど困らないでしょう。オンラインショップでの(税抜き)価格は67.8USDなのですが、送料となんだか税金をとられて結局およそ100USDになってしまいました。ちっとも安くないのでガッカリ。在庫が用意できたら出荷するという連絡があったので、すぐには出荷とならない様子です。新製品ということでまだ作り置きができていないのでしょうか。。。ポーランドからの郵送なので、出荷してもらってからおよそ1週間かかると思われます。この調子だと、手元に届くのは今月末でしょうか?

しばらくは、Make Controllerで作業を続けていくことにします。


めざすはVoIP GW

2008-08-14 01:29:30 | VoIP
さて、今回のAT91SAM7X256を使っての製作目標を定めておくことにします。いつものようにW-SIMをつなげての音声通話に加えてEthernetインタフェースとくれば、これはもうVoIPのゲートウェイ(GW)を作るしかないです。

VoIPプロトコルには、定番のSIPを使用することにします。PC上で動作するフリーのSIPソフトフォンはいくつもありますので、これをインストールしたPC上から発信すると、GWがW-SIMを使って通話を確立するという仕掛けです。着信も同様にして、W-SIMへの着信をSIPを使ってPC上のSIPクライアントに通知することになります。PCとGWの間の音声データは、RTPを使って送受します。コーデックとして(W-SIMが使用している)u-Lawを使う事にすれば、音声データはそのままW-SIMへ送り込めばいいことになるので、GWの処理も簡単です。

SIPのプロトコル・スタックなんて書いたことありませんが、SIPのクライアント(UA)をひとつだけ収容できればいいことにして、発信と着信のために必要最低限の処理だけ実装する方針で手抜きしていけば、まぁなんとかなるのではないでしょうか。

ハードウェアとしては、Make ControllerにW-SIMをつなげなければならないのですが、この暑いさなかにエアコンの効かない部屋でハンダ付けする気になれないので、先にソフトの作業から進めることにしようかと思います。

Make Controller -- TINET動き始める

2008-08-12 08:35:38 | Weblog
AT91SAM7X内蔵のEthernet(EMAC)用にTINETのドライバを作成して、TINETが動き始めました。PHYの部分の操作については、Make Controller用Firmwareに含まれているlwIPのコードを参考にさせてもらいました。どうやらもともとはATMELのサンプルコードがベースになっているようです。

TINET 1.4はこれまでのジャケットでもPPP接続で使用してきていますが、今回はEthernetでの接続になるので、イーサネットのドライバが必要になります。以前TINET 1.3でAT91SAM7X用にドライバを作成したことがあるので、今回はそのコードをもってきて、PHYの部分を若干修正した程度です。ドライバ部分では、CPUのバイトアライメントに応じての設定があるのですが、毎回ここでハマリます。今回も、アライメントに関連するコード部分の修正が必要でした。1.4では移植性を向上させるために新たな定義も追加されて、わかりやすくなっていたのですが、ちゃんと資料を読んでいなかったわたしは逆に時間を費やしてしまいました。やっぱり、ちゃんと資料は読まなくてはと反省。

今のところ、pingのクライアント機能で動作確認をしたところです。この後はUDPを動かしていきますが、TCPは当面使わないで作業を進めるつもりです。TCPを載せるとフラッシュもRAMも喰うので。。


Make Controller -- TOPPERSを動かす

2008-08-09 19:58:25 | Weblog
Make Controllerのアプリケーション・ボードのUART0に、デバック用のシリアルコネクタを付けて、ソフトの開発作業を開始しました。UART0の端子パターンは、RS232CではなくCMOSレベルですので、秋月の変換モジュールを使ってUSBにしています。



とりあえずはTOPPERSが動き始めるところまで作業。すでにAT91SAM7SとAT91SAM7SEで動かしていますから、「移植」というほどの作業でもありません。デバック用のポートをDBGからUART0に変更した程度の作業です。いつも使っているUSBのCDC経由でのアクセスができるところまで確認できました。

Make ControllerにはもともとFreeRTOSlwIPをベースとしたファームウェアが焼いてあったのですが、コントローラボード上のLEDがチカチカするのを確認しただけで秒殺してしまい、TOPPERSに入れ替えてしまいました。次はethernetのドライバを用意して、TINETを動かすことにします。

Make Controllerの気に入らないところ

2008-08-06 23:39:07 | Weblog
届いたばかりのMake Contorollerですが、回路図を見ているうちに、いくつか気に入らない点が見えてきました。

  1. リセットスイッチが無い。JTAG経由でのリセットはできますが、それ以外にはリセットスイッチもありません。Power on resetだけのようです。電源スイッチもありませんから、電源入れ直す必要があります。やはりリセットスイッチがあった方が便利かな。
  2. I2Cが使えない。I2C用のTWIピンがUSBのプルアップ制御とホスト接続検出のために使用されてしまっています。そのため、I2Cのデバイスを接続することができません。
  3. UARTは基板上のパッドだけで、端子は実装されていない。自分で端子をつなぐ必要あり。デバックシリアルのピンはステータスLED用に使われてしまっている。
  4. アプリケーション・ボードの電源端子はターミナルブロックになっており、ねじ止めです。やはりジャックの方が使い易そうです。

上記のうち、2以外はアプリケーション・ボードの問題なので、ベースボードを自作することで解決可能です。2はコントローラ・ボードの問題なので、残念ながらI2Cの使用はあきらめざるをえません。コントローラ・ボードには基本回路は全て載っていますので、ベースボードを自作するとは言っても、ほとんどコネクタ、ジャック、スイッチを用意するだけで済みそうです。