マイコン工作実験日記

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

発信できた

2008-09-07 16:16:03 | VoIP
VoIP GWを使ってX-Liteから実際にW-SIMを使って発信できるようになりました。すでにSIP側で発信に最低限必要な処理は用意してあったので、W-SIM側でのモデム処理のコードを追加して、SSCでの送受信とRTPの送受信を結びつけてやった次第です。



117(時報)を呼んだ時の画面表示と、WireSharkのVoIP Calls解析でのPlayer表示です。Player表示では、上側の音声の18秒から23秒にかけての部分が、30秒間に1度の "プッ、プッ、プッ、ピーン"音に相当します。雰囲気ででますねぇ。



このようにPC側での画面やログを出しても、てんでマイコンを使っているという実感が湧きませんよね。ここは、やはり動画でも用意してAT91SAM7X256で動いていることを示しておきたいものです。しかしマイコン側には何の表示も無いし、音が出るわけでもないので、動画を撮る意味がありません。これでは悲しいので、実用上はさほど意味はないのですが、LCDを付けてみました。



動作状況に応じて表示するようにできたら、動画を撮ろうかと思います。使用しているLCDはaitendoで買ってきたNokia 5110ですが、このLCDについては別途記事を書くことにします。

DHCPを動かす

2008-09-06 00:47:03 | VoIP
作成したVoIP GWボードでethernetが動作することは確認できたので、DHCPを載せてみました。もともとTINETではDHCP_CFGというコンフィギュレーション パラメータが用意されており、tinet_app_config.h等のファイルで指定することができます。しかしながら、このパラメータを指定してもDHCPのクライアント機能が組み込まれるわけではなく、UDP/IP層にてDHCPのパケットをエラーとせずに通すことができるようになるにすぎません。実際のDHCPクライアント機能は、ユーザが自分で組む必要があります。

そこで簡易的なDHCP機能をひとつのタスクとして実装してみました。起動後1秒ほどしてから、TINETが動き始めた頃を見計らってDHCPのDISOVERパケットを送信するようにしています。ほんとは、ethernetのリンク状態の変化も検出してやるべきなのですが、今のところはそこまでの機能は用意していません。

そういえばMACアドレスについての処理もインチキしています。もともとMake ControllerのファームではSPI EEPROMにシリアルナンバーが書き込まれているらしく、MACアドレスのOUI部分としてはAC-DE-48を使用し、下位の部分にシリアルナンバーを使用しているようです。ほんとは、同じように処理するようにTINETのethernetドライバを組むべきなのですが、現在はテキトウなアドレスをhard codedしてしまっています。

AC-DE-48というOUIも怪しそうです。IEEEのページで検索するとPRIVATEとなっており、Make用に割り当てられているわけではないようです。この番号はMACアドレスとしての使い方の説明のページでも使われている番号ですし。。そういうわけで、ちゃんとしたアドレスを使いたければ秋月のEEPROM買ってきた方が良いのでしょう。

VoIP GW用基板

2008-09-01 00:27:12 | VoIP
RTPが流せるところまでソフトの作成が進んだので、次の段階へ進むためにVoIP GW用の専用ボードを作成してみました。Application boardの状態ではW-SIMをつなぐことができませんので。

本来であれば、PropoxのMMnetSAM7xを使ってボードを作成するつもりだったのですが、注文したもののテンでその後の連絡が入りません。Shopで注文のステータスを確認したところ、まだ支払済みになっていないことに気が付きました。とっくに支払いを済ませているのに、ステータスが更新されていないようです。問い合わせのメールを出したのですが、これまた返事がありません。夏休みなんでしょうか。ちょっと不安。



そういうわけで、やむを得ずMake Controlerを引き続き使うことにした次第です。専用ボードといってもハードウェア的にはたいした工作でもありません。基板上に載せるのはほとんどコネクタだけです。

  • JTAGコネクタ
  • リセット・ボタン
  • USB Bコネクタ
  • RJ-45コネクタ
  • W-SIMコネクタ
  • デバック用シリアルコネクタ

電源はまだしばらく、USBコネクタから採ることにします。Controller上にレギュレータとしてLM1117が載っているので、これを使います。

Ethernet部分はパルストランス付きのRJ-45コネクタをつなげばいいだけなので、秋月のコネクタを使うことにしました。変換基板が欲しいところですが、サンハヤトのCK-18ではLED端子の穴とかが無いようです。Sparkfunの変換基板が安いので、コネクタと一緒に買おうかとも考えていたのですが、発売後すぐに売り切れてしまい、そのまま欠品中です。しかたがないので、1.27mmピッチのユニバーサル基板で変換基板を自作しました。

W-SIMコネクタはUS0につないでいます。US1であればモデム信号端子ももっているので、これまではいつもUS1につないでいたのですが、ControllerボードではCTS1に相当するPA9がボード上に実装されているEEPROMのCS端子として使われてしまっています。そのため、RI, DCDは無視して、DSRとDTRはGPIOで処理することにしました。

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のグラフ化機能を用いて表示したものです。


めざすは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をつなげなければならないのですが、この暑いさなかにエアコンの効かない部屋でハンダ付けする気になれないので、先にソフトの作業から進めることにしようかと思います。