IP電話機の製作 PIC24F 2012.6.20


    1.はじめに

      PICマイコンを使った電子工作例は、雑誌やネットでたくさん紹介されているが、IP電話機を製作した例は、あまり見かけない。PICマイコンはメモリサイズが小さく、ネットワーク処理を必要とするIP電話機を製作するのは困難と思われているからだと思うが、最近は、TCP/IPを内蔵したLAN専用チップも容易に入手できるようになり、これらの部品をうまく活用すれば、PICマイコンでもIP電話機の製作ができるのではないかと思い製作に挑戦してみた。


    2.製作概要
    写真1 製作したIP電話機

      使用した主な部品は、16ビットPICマイコンとTCP/IP内蔵LANモジュール、2個のICアンプ、自作のキーユニット、LCD表示器の6個だ。この他には、若干の抵抗とコンデンサを使った。製作したIP電話機の全体写真を写真1に示す。

     電話機本体(ケースはタッパーを採用)にLANケーブルとACアダプタ、それにイヤホーンマイクの3本のケーブルを接続して使用する。送受話機に携帯電話用のイヤホーンマイクを使用したので、回路も簡単で工作も容易となった。スイッチでオンオフが可能なモニタースピーカーや受話音量調整用のボリュームも設けた。SIPプロトコルを実装したので、IP電話交換機やSIPサーバーを通じて他のSIPを使ったIP電話機と通話ができる。なお、本IP電話機を2台製作すれば、直接対向電話機としても使うことが出来る。

     IP電話機のIPアドレスなどの各種設定は、LCD表示器とキーユニットを使って電話機自体で設定できるようにした。設定した内容は、マイコンのプログラムメモリ(FLASHメモリ)に記憶させるので電源を切っても保存される。毎回設定する必要はない。


    写真2 左側面に、スピーカースィッチとボリューム、イヤホーンマイクジャック
    写真3 右側面にLANとACアダプタのジャック

    3.設計と製作

    図1 IP電話機回路図

      製作したIP電話機の回路を図1に示す。今回使用したPICマイコンは、マイクロチップ社の16ビットマイコン、「PIC24FJ64GA002」だ。プログラムメモリが64KB、データメモリが8KBとPICマイコンとしては比較的メモリ容量が大きいことと、DIPタイプで工作が容易かつ入手しやすいことから、このマイコンを採用した。電源電圧は3.3Vだ。内蔵の高速RC発振器を使うことで外付けの水晶発振子は不要とした。

     TCP/IP内蔵LANモジュールは、韓国WIZNET社の「WIZ812MJ」を使用した。このモジュールに搭載されているICチップ「W5100」がMACプロトコルやTCP/IPプロトコルを全て処理してくれるので、PICマイコン側でのネットワーク対応部分のプログラム作成が不要となる。

    PIC24FJ64GA002
    WIZ812MJ
    W5100

     設計開始当初、プログラムメモリが64KBではIP電話機の製作は無理かと思っていたのだが、ネットワーク周りのプログラムが不要であることや、SIPプロトコルの機能を発着信の基本的な通話機能に限定したことで、結果として、40数KB程度のプログラムサイズでIP電話機を実現することができた。

     「PIC24FJ64GA002」は、28ピンDIPタイプだ。周辺機器との接続に使えるI/Oピンの数は、それほど多くない。そこで、LANモジュールとの接続にはSPIを採用し、LCD表示器については、I2C接続が可能なものを選択して少ないピン数で接続するようにした。

     入手したLCD表示器は、「低電圧I2C液晶モジュール」というもので、16x2行のキャラクタ表示と数個のアイコンが表示できるものだ。3.3Vで動作しマイコンとはI2Cの2本の信号線で接続する。大きさも46mmx32mmとコンパクトで、先述の「WIZ812MJ」とともに、ストロベリー・リナックス社から購入した。

     発信時のダイヤル操作に必要なキーユニットは、タクトスィッチとユニバーサル基板を使って自作した。キートップには、100円電卓のキートップとキーカバーを流用した。ボタンの数は、「ダイヤルボタン」の他に「オンフック」、「オフフック」など都合18個のキーがある。このキーユニットとマイコンとの接続は、接続ピン数がわずか3ピンで済むようにキーの操作判定をデジタル入力処理ではなくアナログ入力処理で行うようにした。

    自作したキーユニット
    100円電卓のキートップをかぶせた
    低電圧I2C液晶モジュール
    アイコンも表示できる

    赤い基板がLANモジュール、裏返して取り付けている。
    PICとOPアンプ、オーディオアンプは、ユニバーサル基板に搭載した。

     イヤホーンマイクからの送話信号の増幅には、単電源、入出力フルスィング可能なOPアンプ「NJM2732」を採用し、OPアンプの出力をPICマイコンのアナログ入力に接続しデジタル変換している。

     採用したPIC24FJ64には、A/D変換モジュールは内蔵されているがD/A変換モジュールは内蔵されていない。そこで、受話信号のD/A変換には、PWM出力による変換方式を採用し外付けのD/A変換モジュールなどは不要とした。受信した音声信号でPWMのパルス幅を変調し、抵抗とコンデンサによる簡単なフィルタにより、音声信号に戻した後、オーデイオアンプIC「LM386」で増幅し、モニタースピーカーとイヤホーンに出力している。

     電話機で必要となるダイヤルトーンやリングバックトーン、ビジートーンなども、専用の外付け発振回路は設けないで、このPWM回路により、全てマイコンで生成した。あらかじめプログラム内部にトーン信号のサンプリングデータを準備しておき、PWMにより適宜出力させている。

     シンプルに作ることを目標に製作したのでプログラム作成においても、リアルタイムOSなどは採用していない。「発信中」、「呼び出し中」、「着信中」など電話機の各状態毎の処理関数を作成し、状態遷移に従って処理していくようにプログラムした。SIPパケットやRTPパケットの受信確認は、PICマイコンから随時LANモジュールにポーリングして確認するようにした。

     マイクから入力された音声信号を8KHzの周期でサンプリングしたり、受信した音声データを8KHzの周期で再生するためのタイミング発生には、インターバルタイマー割り込みを活用した。

     SIPについては、RFC3261を参考にプログラムしたが、最低限の基本通信が出来ることを目標に仕様を限定している。リクエストメッセージは、REGISTER、INVITE、CANCEL、BYE、ACK、PRACK、UPDATEのみ処理できるようにした。

     運用するSIPサーバーによっては、IP電話機からREGISTERやINVITEリクエストを送信すると、その応答として401や407レスポンスで認証を要求してくることがある。 この認証に応答する機能は必要な機能であり、きちんとプログラムしておいた。


    4. 使い方

    4−1 操作キー

     自作したキーには、100円電卓のキートップを被せているが、キーの刻印は実際の機能とは異なっている。キーの機能は次のとおり。

      キートップ刻印
      ON/C
      OFF
      ×
      ÷
      キーの機能
      OnHook
      OffHook
      Enter
      Clear

      #$%

      ABC

      DEF

      GHI

      JKL

      MNO

      PQR

      TUV

      WXYZ

      .@/

      &'(
        
      OnHook受話機を下ろす
      OffHook受話機を上げる
      左カーソル移動
      右カーソル移動
      Enter選択・決定
      Clear入力消去・一文字削除
      0-9*#ダイヤルボタン

     IP電話機の設定パラメータであるSIP-IDやSIPパスワードの入力では、英文字の入力が必要であり、 ダイヤルボタンには、携帯電話のキーと同様に英文字キーを割り当てた。
     英文字入力モードと数字入力モードの切り替えは、左カーソル移動キーと右カーソル移動キーを同時に押すことにより行える。

     設定パラメータ入力中の文字編集は、カーソル移動キーやClearキーを使って行う。Enterキーで入力を確定する。

    4−2 設定パラメータ

     IP電話機の使用に先だって設定が必要となるパラメータは次のとおり。

     ネットワーク端末としての情報
      IPアドレス、ネットマスク、デフォルトゲートウェイアドレス

     SIP端末としての情報
      電話番号
      SIPポート番号,RTPポート番号
      SIP-ID,SIPパスワード
      SIPサーバーのIPアドレス,SIPサーバーのSIPポート番号,SIPサーバーのドメイン名
      REGISTERの有効時間
      セッション監視タイマー値
      呼び出しタイムアウト時間

     IP電話機が待ち受け状態にある時に、左カーソル移動キーと右カーソル移動キーを同時に押すとパラメータ入力モードとなり、LCDの上部にパラメータ名が、LCD下部に現在の設定値が表示される。

     キーを操作してパラメータを入力し、Enterキーを押すと、次のパラメータ入力となる。全てのパラメータを入力し終えると、入力されたパラメータは、プログラムメモリであるFLASHメモリのアドレス"A400" 以降に保存され、待ち受け状態に戻る。プログラムサイズが40数キロバイトで納まっているため、"A400"以降に書き込んでも動作に問題はない。

     IP電話機は、電源投入時の初期化処理の段階で、FLASHメモリの"A400"番地以降に保存されたパラメータを読み取って動作を開始する。パラメータがまだ一度も保存されていない場合には、 プログラムでコードされたデフォルトの値で動作を開始する。

    4−3 REGISTERメッセージの送信

     待ち受け状態にある時に、Enterキーを押すとREGISTERメッセージを送信することができる。

     LCDに、REGISTERメッセージの送信確認が表示されるので、 再度Enterキーを押すとSIPサーバーにREGISTERメッセージを送信する。 送信が成功すると、以後、設定パラメータであるREGISTER有効時間で指定された時間の半分の時間間隔で、自動でREGISTERメッセージを再送信する。

     IP電話機で着信するためには、予めSIPサーバーにREGISTERメッセージを送信し、SIPサーバーにIP電話機のIPアドレスを教えてやらなければならない。

    4−4 ダイヤル発信

     待ち受け状態にある時、OffHookボタンを押すと、イヤフォーンから、この時スピーカースィッチがオンになっていればスピーカーからもツーという400Hzのダイヤルトーンが出力される。ここで、OnHookボタンを押すと、 ダイヤルトーンは停止し、待ち受け状態に戻る。

     待ち受け状態にある時や、ダイヤルトーンが出力されている時に、数字キーで掛けたい先の電話番号を入力し、Enterキーを押すと発信動作を開始する。具体的には、SIPサーバーにINVITEリクエストを送信し、 必要に応じてSIP認証応答を行い、SIPサーバーからの呼び出し応答を待つ。電話番号入力途中で、OnHookボタンを押すと待ち受け状態に戻る。

     SIPサーバーから、"180 Ringing" レスポンスを受け取ると、呼び出し中音(リングバックトーン)がイヤフォーンやスピーカーから出力される。相手が応答すると、呼び出し音は停止し、通話を開始することが出来る。

     相手が話中で、SIPサーバーから"486 Busy Here"レスポンスを受け取ると話中音がイヤフォーンやスピーカーから出力される。相手が応答するまでに、OnHookボタンを押すと呼び出しをキャンセルする。この時、 SIPサーバーにCANCELリクエストを送信する。

     通話中に、数字キーを押すと、ピポパのDTMF音を音声信号に代えて送信するが、モニター出力していないので、送出音は聞こえない。

     通話中にOnHookボタンを押すと通話を切断し、待ち受け状態に戻る。通話中に、相手が先に切断した場合には、イヤフォーンやスピーカーから話中音が出力される。OnHookボタンを押すことにより、話中音は停止し、 待ち受け状態に戻る。

     ダイヤルした電話番号は、5番号まで記憶され、待ち受け状態や、ダイヤルトーン送出時に、右カーソル移動キーを押すと、記憶された番号がLCDに表示され、リダイヤル発信することができる。

    4−5 着信

     待ち受け状態の時に、SIPサーバーからINVITEリクエストを受信すると、イヤフォーンやスピーカーから呼び出し音が出力される。ここで、OffHookボタンを押すと、通話を行うことが出来る。

     通話中に、数字キーを押すと、ピポパのDTMF音を音声信号に代えて送信するが、モニター出力していないので、送出音は聞こえない。

     通話中にOnHookボタンを押すと通話を切断し、待ち受け状態に戻る。通話中に、相手が先に切断した場合には、イヤフォーンやスピーカーから話中音が出力される。OnHookボタンを押すことにより、話中音は停止し、 待ち受け状態に戻る。


    5. プログラム

     IP電話機のプログラムは、MPLAB-IDE上でC言語で作成し、C30コンパイラにてコンパイルした。

     プロジェクトファイルを構成する主なソースプログラムは、次のとおり。

      digest.cmd5を使ったダイジェスト認証のためのハッシュ計算を行う
      dtmf.c通話中にキーを押した時のDTMFトーンを生成する
      key.cアナログ入力によるキー入力判定処理を行う
      lcd.cI2Cによる液晶モジュール操作関数
      main.cIP電話機メイン関数
      md5.cmd5ハッシュ計算関数
      message.cSIPメッセージの作成を行う
      setup.cIPアドレスなどネットワーク情報の設定処理を行う
      sound.c送話信号のサンプリング、受話信号の再生を行う
      sysconf.cシステムの初期化、パケット送受信処理を行う
      ua.cSIPプロトコルを処理する
      W5100.cW5100チップの操作関数

     コンパイル時のオプション指定に少し注意が必要だ。MPLAB C30のMemoryModelオプションは、全て Large model を選択するとともに、Constants in code space を選択する。こうしておかないとリンクでエラーがでてしまう。

     ソースファイル別の補足を纏めておく。

      digest.c, md5.c

      REGISTERやINVITEを送信した時にSIPサーバーから要求されるMD5ダイジェスト認証のハッシュ値を計算する関数群である。
      md5.c は、RFCで公開されているプログラムそのものであり、WIZNETのサンプルプログラムに含まれていたものをそのまま使った。

     dtmf.c

       Microchip社が公開しているサンプルプログラムを元に作成した。DTMF信号を構成する7種類のトーン信号について、予めデジタルサンプリングデータを プログラム内に配列データとして準備しておくのだが、各信号毎に、異なるサイクル数分を準備しておくのがミソだ。これにより、全ての信号の生成誤差を1%未満に納めることが出来る。
      PB tone mapping
      120913361477
      697
      1
      2
      3
      770
      4
      5
      6
      852
      7
      8
      9
      941
      *
      0
      #
      freq.cyclessamples by 8Khzreal frequency
      6972cycles
      23sample
      16,000/23696 -0.2%
      7703cycles
      31sample
      24,000/31774 +0.5%
      8523cycles
      28sample
      24,000/28857 +0.6%
      9412cycles
      17sample
      16,000/17941 0%
      12095cycles
      33sample
      40,000/331212 +0.3%
      13361cycles
      6sample
      8,000/ 61333 -0.2%
      14775cycles
      27sample
      40,000/271481 +0.3%

     key.c

       本IP電話機では、キー入力とマイクからの音声信号をA/D変換する必要があり、PIC24FJ64のA/D変換モジュールは一つしかないので、4つのアナログ入力端子を順次スキャンさせる こととした。マイク入力のA/D変換とキーの入力判定は、他のプログラムの動作とは無関係に、バックグラウンドで常時行うようにプログラムした。具体的には、A/D変換を125usec周期で 自動で連続して行うこととし、A/D変換完了毎に発生する割り込み処理の中で、キーの入力判定とマイク入力の読み取り処理を行った。

       キーの入力判定は、チャタリングの影響を回避するために、割り込み4回毎(500usec)に入力を読み取り、10回連続同じ値が読めた時にキーの値を確定させている。 マイク入力のA/D変換結果は、グローバル変数に格納され、別のプログラムモジュール(sound.c)が、8KHzのサンプルタイミングで使うようになっている。

     sound.c

       ダイヤルトーンやリングバックトーンの生成の他、送信音声パケットのエンコード、受信音声パケットのデコードなどを行っている。音声信号は、G711u-lawによるエンコード、デコード処理を 行わせている。受信音声パケットのゆらぎを補償するジッタバッファは、PICのデータメモリが8Kバイトと小さいために、5パケット分しか確保していない。

     message.c

       RFC3261に基づくSIPリクエストやSIPレスポンスのメッセージ作成を行っている。ほとんどが文字列処理であり、自作の "sprintf()" 関数である mysprintf() を多用している。 MPLABで提供される sprintf()は、サイズも大きくヒープメモリを必要とするので、あえて自作の関数を用意した(mysprintf()は、pic_print.c ファイルにある)。 乱数発生関数もMPLABで提供されるライブラリを使わなくて済むように自作した。

     ua.c

       IP電話の発着信処理を行うメインのプログラムである。IP電話機の状態を次の8つのステートに分割し、各ステートに応じたSIPメッセージの処理やトーンの出力を行っている。
        ステートマクロ状態説明
        STATE_DISCONNECT_ON_HOOK電話機のアイドル状態、着信監視、キーの入力監視を行う
        STATE_DISCONNECT_OFF_HOOK話中音を出力している状態、1分間またはオンフックで話中音停止
        STATE_CALLING発信処理(INVITEの送信)をしている状態
        STATE_CANCELING呼び出しを中止した状態(CANCELを送信)
        STATE_PROGRESS相手呼び出し処理進行中の状態(183を受信)
        STATE_RINGING相手を呼び出している状態(180を受信)呼び出し中音を出力する。
        STATE_CONNECT相手と接続を完了し(200OKを受信)、通話を継続している状態。
        STATE_INCOMMING着信(INVITEを受信)があり、着信ベルを出力している状態


    6. 2台のIP電話機で直接通話する方法

     製作したIP電話機は、SIPサーバーやIP-PBXと接続して使用することを考慮して設計・製作したが、サーバーやPBXが無くても、 このIP電話機2台を使って対向電話として直接通話することもできる。

     その方法は、IP電話機に設定するパラメータの内、SIPサーバーのIPアドレス/SIPポート番号に、もう一方のIP電話機のIPアドレス/SIPポート番号を設定し、相手の 電話番号をダイヤルして発信すれば、直ちに接続することができる。この場合には、予めREGISTERメッセージを送信しておく必要はない。仮にREGISTERメッセージを送信すると、 送信エラーとなる。また、設定したSIP-IDやSIPパスワード,サーバーのドメイン名は意味がない。